@apipass/design-system 8.1.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/embedded-styles.js +2 -2
- package/dist/lib/style.css +1 -1
- package/dist/lib/ui/primitives/Select/MultiSelect.cjs +1 -1
- package/dist/lib/ui/primitives/Select/MultiSelect.cjs.map +1 -1
- package/dist/lib/ui/primitives/Select/MultiSelect.js +138 -68
- package/dist/lib/ui/primitives/Select/MultiSelect.js.map +1 -1
- package/dist/types/ui/primitives/Select/MultiSelect.d.ts +17 -3
- package/package.json +5 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),R=require("../../../vendor/clsx/dist/clsx.cjs"),i=require("react"),m=require("react-aria-components");;/* empty css */const B=require("../../icons/IconChevronDown.cjs"),E=require("../../hooks/useOverlayPortal.cjs"),j=require("../Fieldset/Fieldset.cjs"),C=require("../ListBox/ListBox.cjs"),D=require("../Input/Input.cjs");function q(n){const{id:e}=n.props;return e??n.key??""}function F(n){const{textValue:e,children:t}=n.props;return e!==void 0?e:typeof t=="string"?t:""}function I(n,e){i.Children.forEach(n,t=>{i.isValidElement(t)&&e(t)})}function L(n){const e=new Set;return I(n,t=>e.add(q(t))),e}function M(n,e,t){return i.Children.toArray(n).filter(s=>i.isValidElement(s)&&t(F(s),e))}function O(n,e,t){const s=new Set(e.map(String)),o=l=>s.has(String(l)),c=[...n].filter(l=>!o(l)),a=t==="all"?e:[...t].filter(o);return new Set([...c,...a])}function k(n,e){const t=new Set([...e].map(String)),s=[];return I(n,o=>{t.has(String(q(o)))&&s.push(F(o))}),s.join(", ")}function A({children:n,selectedKeys:e,onSelectionChange:t,disallowEmptySelection:s,listLabel:o,searchPlaceholder:c,emptyStateText:a}){const{contains:l}=m.useFilter({sensitivity:"base"}),[v,y]=i.useState(""),f=i.useRef(null),u=M(n,v,l),p=u.map(q);function b(h){var d,g;h.key!=="ArrowDown"||u.length===0||(h.preventDefault(),(g=(d=f.current)==null?void 0:d.querySelector('[role="listbox"]'))==null||g.focus())}return r.jsxs("div",{ref:f,className:"select-search-panel",children:[r.jsx(m.TextField,{"aria-label":c,value:v,onChange:y,autoFocus:!0,children:r.jsx(D.Input,{className:"select-search-input",placeholder:c,onKeyDown:b})}),r.jsx(C.ListBox,{"aria-label":o,selectionMode:"multiple",escapeKeyBehavior:"none",disallowEmptySelection:s,selectedKeys:e,onSelectionChange:h=>t(O(e,p,h)),renderEmptyState:()=>r.jsx("span",{className:"select-empty-state",children:a}),children:u})]})}function V({className:n,label:e,description:t,errorMessage:s,placeholder:o,children:c,selectedKeys:a,onSelectionChange:l,isDisabled:v,isInvalid:y,disallowEmptySelection:f,"aria-label":u,...p}){const b=R.clsx(n,"select-container"),h=E.useOverlayPortalContainer(),d=i.useRef(null),[g,N]=i.useState(),T=i.useCallback(()=>{d.current&&N(`${d.current.offsetWidth}px`)},[]);i.useLayoutEffect(()=>{T();const x=d.current;if(!x||typeof ResizeObserver>"u")return;const w=new ResizeObserver(T);return w.observe(x),()=>w.disconnect()},[T]);const S=k(c,a);return r.jsx("div",{className:b,children:r.jsxs(j.Field,{children:[e&&r.jsx(j.Label,{children:e}),r.jsxs(m.MenuTrigger,{children:[r.jsxs(m.Button,{ref:d,className:"select","aria-label":u,isDisabled:v,"data-invalid":y||void 0,children:[r.jsx("span",{className:"select-value","data-placeholder":S===""||void 0,title:S||void 0,children:S===""?o:S}),r.jsx(B.IconChevronDown,{"aria-hidden":"true"})]}),r.jsx(m.Popover,{className:"select-popover",style:{"--trigger-width":g},UNSTABLE_portalContainer:h,children:p.isSearchable?r.jsx(A,{listLabel:e??u,selectedKeys:a,onSelectionChange:l,disallowEmptySelection:f,searchPlaceholder:p.searchPlaceholder,emptyStateText:p.emptyStateText,children:c}):r.jsx(C.ListBox,{"aria-label":e??u,autoFocus:!0,selectionMode:"multiple",escapeKeyBehavior:"none",disallowEmptySelection:f,selectedKeys:a,onSelectionChange:x=>l(x==="all"?L(c):new Set(x)),children:c})})]}),t&&r.jsx(j.Description,{children:t}),r.jsx(j.FieldError,{children:s})]})})}exports.MultiSelectField=V;
|
|
2
2
|
//# sourceMappingURL=MultiSelect.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.cjs","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): string {\n const { id } = item.props as { id?: RACKey };\n return String(id ?? item.key ?? \"\");\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(itemKey(item))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\nexport interface MultiSelectFieldProps extends SharedFieldProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n disallowEmptySelection?: boolean;\n \"aria-label\"?: string;\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","selectedItemsText","selectedKeys","selected","texts","MultiSelectField","className","label","description","errorMessage","placeholder","onSelectionChange","isDisabled","isInvalid","disallowEmptySelection","ariaLabel","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","useRef","triggerWidth","setTriggerWidth","useState","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","jsx","Field","Label","RACMenuTrigger","jsxs","RACButton","IconChevronDown","RACPopover","ListBox","Description","FieldError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MultiSelect.cjs","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Input,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n TextField as RACTextField,\n useFilter,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): RACKey {\n const { id } = item.props as { id?: RACKey };\n return id ?? item.key ?? \"\";\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\ntype TextMatcher = (text: string, searchText: string) => boolean;\n\nfunction matchingItems(\n children: React.ReactNode,\n searchText: string,\n matches: TextMatcher,\n): React.ReactElement[] {\n return React.Children.toArray(children).filter(\n (child): child is React.ReactElement =>\n React.isValidElement(child) && matches(itemText(child), searchText),\n );\n}\n\nfunction keepHiddenSelection(\n previousKeys: Iterable<RACKey>,\n visibleKeys: RACKey[],\n visibleSelection: RACSelection,\n): Set<RACKey> {\n const visible = new Set(visibleKeys.map(String));\n const isVisible = (key: RACKey) => visible.has(String(key));\n const hiddenSelected = [...previousKeys].filter((key) => !isVisible(key));\n const visibleSelected =\n visibleSelection === \"all\"\n ? visibleKeys\n : [...visibleSelection].filter(isVisible);\n return new Set([...hiddenSelected, ...visibleSelected]);\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(String(itemKey(item)))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\ninterface MultiSelectOptionsProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n disallowEmptySelection?: boolean;\n}\n\ninterface MultiSelectFieldBaseProps\n extends SharedFieldProps,\n MultiSelectOptionsProps {\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n \"aria-label\"?: string;\n}\n\nexport interface MultiSelectSearchProps {\n isSearchable: true;\n searchPlaceholder: string;\n emptyStateText: string;\n}\n\ninterface MultiSelectWithoutSearchProps {\n isSearchable?: false;\n searchPlaceholder?: never;\n emptyStateText?: never;\n}\n\nexport type MultiSelectFieldProps = MultiSelectFieldBaseProps &\n (MultiSelectSearchProps | MultiSelectWithoutSearchProps);\n\nfunction SearchableOptions({\n children,\n selectedKeys,\n onSelectionChange,\n disallowEmptySelection,\n listLabel,\n searchPlaceholder,\n emptyStateText,\n}: MultiSelectOptionsProps &\n Omit<MultiSelectSearchProps, \"isSearchable\"> & { listLabel?: string }) {\n const { contains } = useFilter({ sensitivity: \"base\" });\n const [searchText, setSearchText] = useState(\"\");\n const panelRef = useRef<HTMLDivElement>(null);\n const visibleItems = matchingItems(children, searchText, contains);\n const visibleKeys = visibleItems.map(itemKey);\n\n function moveFocusToList(event: React.KeyboardEvent<HTMLInputElement>) {\n if (event.key !== \"ArrowDown\" || visibleItems.length === 0) return;\n event.preventDefault();\n panelRef.current?.querySelector<HTMLElement>('[role=\"listbox\"]')?.focus();\n }\n\n return (\n <div ref={panelRef} className=\"select-search-panel\">\n <RACTextField\n aria-label={searchPlaceholder}\n value={searchText}\n onChange={setSearchText}\n autoFocus\n >\n <Input\n className=\"select-search-input\"\n placeholder={searchPlaceholder}\n onKeyDown={moveFocusToList}\n />\n </RACTextField>\n <ListBox\n aria-label={listLabel}\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(keepHiddenSelection(selectedKeys, visibleKeys, keys))\n }\n renderEmptyState={() => (\n <span className=\"select-empty-state\">{emptyStateText}</span>\n )}\n >\n {visibleItems}\n </ListBox>\n </div>\n );\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n ...searchProps\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n {searchProps.isSearchable ? (\n <SearchableOptions\n listLabel={label ?? ariaLabel}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n disallowEmptySelection={disallowEmptySelection}\n searchPlaceholder={searchProps.searchPlaceholder}\n emptyStateText={searchProps.emptyStateText}\n >\n {children}\n </SearchableOptions>\n ) : (\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n )}\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","matchingItems","searchText","matches","keepHiddenSelection","previousKeys","visibleKeys","visibleSelection","visible","isVisible","key","hiddenSelected","visibleSelected","selectedItemsText","selectedKeys","selected","texts","SearchableOptions","onSelectionChange","disallowEmptySelection","listLabel","searchPlaceholder","emptyStateText","contains","useFilter","setSearchText","useState","panelRef","useRef","visibleItems","moveFocusToList","event","_b","_a","jsxs","jsx","RACTextField","Input","ListBox","MultiSelectField","className","label","description","errorMessage","placeholder","isDisabled","isInvalid","ariaLabel","searchProps","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","triggerWidth","setTriggerWidth","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","Field","Label","RACMenuTrigger","RACButton","IconChevronDown","RACPopover","Description","FieldError"],"mappings":"kcAwBA,SAASA,EAAQC,EAAkC,CACjD,KAAM,CAAE,GAAAC,GAAOD,EAAK,MACpB,OAAOC,GAAMD,EAAK,KAAO,EAC3B,CAEA,SAASE,EAASF,EAAkC,CAClD,KAAM,CAAE,UAAAG,EAAW,SAAAC,CAAA,EAAaJ,EAAK,MAIrC,OAAIG,IAAc,OAAkBA,EAC7B,OAAOC,GAAa,SAAWA,EAAW,EACnD,CAEA,SAASC,EACPD,EACAE,EACA,CACAC,EAAM,SAAS,QAAQH,EAAWI,GAAU,CACtCD,EAAM,eAAeC,CAAK,KAASA,CAAK,CAC9C,CAAC,CACH,CAEA,SAASC,EAAYL,EAAwC,CAC3D,MAAMM,MAAW,IACjB,OAAAL,EAAYD,EAAWJ,GAASU,EAAK,IAAIX,EAAQC,CAAI,CAAC,CAAC,EAChDU,CACT,CAIA,SAASC,EACPP,EACAQ,EACAC,EACsB,CACtB,OAAON,EAAM,SAAS,QAAQH,CAAQ,EAAE,OACrCI,GACCD,EAAM,eAAeC,CAAK,GAAKK,EAAQX,EAASM,CAAK,EAAGI,CAAU,CAAA,CAExE,CAEA,SAASE,EACPC,EACAC,EACAC,EACa,CACb,MAAMC,EAAU,IAAI,IAAIF,EAAY,IAAI,MAAM,CAAC,EACzCG,EAAaC,GAAgBF,EAAQ,IAAI,OAAOE,CAAG,CAAC,EACpDC,EAAiB,CAAC,GAAGN,CAAY,EAAE,OAAQK,GAAQ,CAACD,EAAUC,CAAG,CAAC,EAClEE,EACJL,IAAqB,MACjBD,EACA,CAAC,GAAGC,CAAgB,EAAE,OAAOE,CAAS,EAC5C,WAAW,IAAI,CAAC,GAAGE,EAAgB,GAAGC,CAAe,CAAC,CACxD,CAEA,SAASC,EACPnB,EACAoB,EACQ,CACR,MAAMC,EAAW,IAAI,IAAI,CAAC,GAAGD,CAAY,EAAE,IAAI,MAAM,CAAC,EAChDE,EAAkB,CAAA,EACxB,OAAArB,EAAYD,EAAWJ,GAAS,CAC1ByB,EAAS,IAAI,OAAO1B,EAAQC,CAAI,CAAC,CAAC,GAAG0B,EAAM,KAAKxB,EAASF,CAAI,CAAC,CACpE,CAAC,EACM0B,EAAM,KAAK,IAAI,CACxB,CAiCA,SAASC,EAAkB,CACzB,SAAAvB,EACA,aAAAoB,EACA,kBAAAI,EACA,uBAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,eAAAC,CACF,EACyE,CACvE,KAAM,CAAE,SAAAC,CAAA,EAAaC,EAAAA,UAAU,CAAE,YAAa,OAAQ,EAChD,CAACtB,EAAYuB,CAAa,EAAIC,EAAAA,SAAS,EAAE,EACzCC,EAAWC,EAAAA,OAAuB,IAAI,EACtCC,EAAe5B,EAAcP,EAAUQ,EAAYqB,CAAQ,EAC3DjB,EAAcuB,EAAa,IAAIxC,CAAO,EAE5C,SAASyC,EAAgBC,EAA8C,SACjEA,EAAM,MAAQ,aAAeF,EAAa,SAAW,IACzDE,EAAM,eAAA,GACNC,GAAAC,EAAAN,EAAS,UAAT,YAAAM,EAAkB,cAA2B,sBAA7C,MAAAD,EAAkE,QACpE,CAEA,OACEE,EAAAA,KAAC,MAAA,CAAI,IAAKP,EAAU,UAAU,sBAC5B,SAAA,CAAAQ,EAAAA,IAACC,EAAAA,UAAA,CACC,aAAYf,EACZ,MAAOnB,EACP,SAAUuB,EACV,UAAS,GAET,SAAAU,EAAAA,IAACE,EAAAA,MAAA,CACC,UAAU,sBACV,YAAahB,EACb,UAAWS,CAAA,CAAA,CACb,CAAA,EAEFK,EAAAA,IAACG,EAAAA,QAAA,CACC,aAAYlB,EACZ,cAAc,WACd,kBAAkB,OAClB,uBAAAD,EACA,aAAAL,EACA,kBAAoBd,GAClBkB,EAAkBd,EAAoBU,EAAcR,EAAaN,CAAI,CAAC,EAExE,iBAAkB,IAChBmC,EAAAA,IAAC,OAAA,CAAK,UAAU,qBAAsB,SAAAb,EAAe,EAGtD,SAAAO,CAAA,CAAA,CACH,EACF,CAEJ,CAEO,SAASU,EAAiB,CAC/B,UAAAC,EACA,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,YAAAC,EACA,SAAAlD,EACA,aAAAoB,EACA,kBAAAI,EACA,WAAA2B,EACA,UAAAC,EACA,uBAAA3B,EACA,aAAc4B,EACd,GAAGC,CACL,EAA0B,CACxB,MAAMC,EAAaC,EAAAA,KAAKV,EAAW,kBAAkB,EAC/CW,EAAkBC,EAAAA,0BAAA,EAClBC,EAAazB,EAAAA,OAA0B,IAAI,EAC3C,CAAC0B,EAAcC,CAAe,EAAI7B,WAAA,EAElC8B,EAAiBC,EAAAA,YAAY,IAAM,CACnCJ,EAAW,SACbE,EAAgB,GAAGF,EAAW,QAAQ,WAAW,IAAI,CAEzD,EAAG,CAAA,CAAE,EAELK,EAAAA,gBAAgB,IAAM,CACpBF,EAAA,EACA,MAAMG,EAAUN,EAAW,QAC3B,GAAI,CAACM,GAAW,OAAO,eAAmB,IAAa,OACvD,MAAMC,EAAW,IAAI,eAAeJ,CAAc,EAClD,OAAAI,EAAS,QAAQD,CAAO,EACjB,IAAMC,EAAS,WAAA,CACxB,EAAG,CAACJ,CAAc,CAAC,EAEnB,MAAMK,EAAahD,EAAkBnB,EAAUoB,CAAY,EAE3D,OACEqB,EAAAA,IAAC,MAAA,CAAI,UAAWc,EACd,gBAACa,QAAA,CACE,SAAA,CAAArB,GAASN,EAAAA,IAAC4B,EAAAA,OAAO,SAAAtB,CAAA,CAAM,SACvBuB,EAAAA,YAAA,CACC,SAAA,CAAA9B,EAAAA,KAAC+B,EAAAA,OAAA,CACC,IAAKZ,EACL,UAAU,SACV,aAAYN,EACZ,WAAAF,EACA,eAAcC,GAAa,OAE3B,SAAA,CAAAX,EAAAA,IAAC,OAAA,CACC,UAAU,eACV,mBAAkB0B,IAAe,IAAM,OACvC,MAAOA,GAAc,OAEpB,SAAAA,IAAe,GAAKjB,EAAciB,CAAA,CAAA,EAErC1B,EAAAA,IAAC+B,EAAAA,gBAAA,CAAgB,cAAY,MAAA,CAAO,CAAA,CAAA,CAAA,EAEtC/B,EAAAA,IAACgC,EAAAA,QAAA,CACC,UAAU,iBACV,MAAO,CAAE,kBAAmBb,CAAA,EAC5B,yBAA0BH,EAEzB,WAAY,aACXhB,EAAAA,IAAClB,EAAA,CACC,UAAWwB,GAASM,EACpB,aAAAjC,EACA,kBAAAI,EACA,uBAAAC,EACA,kBAAmB6B,EAAY,kBAC/B,eAAgBA,EAAY,eAE3B,SAAAtD,CAAA,CAAA,EAGHyC,EAAAA,IAACG,EAAAA,QAAA,CACC,aAAYG,GAASM,EACrB,UAAS,GACT,cAAc,WACd,kBAAkB,OAClB,uBAAA5B,EACA,aAAAL,EACA,kBAAoBd,GAClBkB,EACElB,IAAS,MAAQD,EAAYL,CAAQ,EAAI,IAAI,IAAIM,CAAI,CAAA,EAIxD,SAAAN,CAAA,CAAA,CACH,CAAA,CAEJ,EACF,EACCgD,GAAeP,EAAAA,IAACiC,EAAAA,YAAA,CAAa,SAAA1B,CAAA,CAAY,EAC1CP,EAAAA,IAACkC,EAAAA,YAAY,SAAA1B,CAAA,CAAa,CAAA,CAAA,CAC5B,CAAA,CACF,CAEJ"}
|
|
@@ -1,113 +1,183 @@
|
|
|
1
|
-
import { jsx as n, jsxs as
|
|
2
|
-
import { clsx as
|
|
3
|
-
import
|
|
4
|
-
import { MenuTrigger as
|
|
1
|
+
import { jsx as n, jsxs as S } from "react/jsx-runtime";
|
|
2
|
+
import { clsx as D } from "../../../vendor/clsx/dist/clsx.js";
|
|
3
|
+
import x, { useRef as N, useState as F, useCallback as k, useLayoutEffect as L } from "react";
|
|
4
|
+
import { MenuTrigger as M, Button as O, Popover as V, useFilter as j, TextField as A } from "react-aria-components";
|
|
5
5
|
/* empty css */
|
|
6
|
-
import { IconChevronDown as
|
|
7
|
-
import { useOverlayPortalContainer as
|
|
8
|
-
import { Field as
|
|
9
|
-
import { ListBox as
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
import { IconChevronDown as W } from "../../icons/IconChevronDown.js";
|
|
7
|
+
import { useOverlayPortalContainer as z } from "../../hooks/useOverlayPortal.js";
|
|
8
|
+
import { Field as K, Label as q, Description as H, FieldError as P } from "../Fieldset/Fieldset.js";
|
|
9
|
+
import { ListBox as E } from "../ListBox/ListBox.js";
|
|
10
|
+
import { Input as U } from "../Input/Input.js";
|
|
11
|
+
function w(r) {
|
|
12
|
+
const { id: e } = r.props;
|
|
13
|
+
return e ?? r.key ?? "";
|
|
13
14
|
}
|
|
14
|
-
function
|
|
15
|
-
const { textValue: e, children:
|
|
16
|
-
return e !== void 0 ? e : typeof
|
|
15
|
+
function I(r) {
|
|
16
|
+
const { textValue: e, children: t } = r.props;
|
|
17
|
+
return e !== void 0 ? e : typeof t == "string" ? t : "";
|
|
17
18
|
}
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
function R(r, e) {
|
|
20
|
+
x.Children.forEach(r, (t) => {
|
|
21
|
+
x.isValidElement(t) && e(t);
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
|
-
function
|
|
24
|
+
function _(r) {
|
|
24
25
|
const e = /* @__PURE__ */ new Set();
|
|
25
|
-
return
|
|
26
|
+
return R(r, (t) => e.add(w(t))), e;
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
function $(r, e, t) {
|
|
29
|
+
return x.Children.toArray(r).filter(
|
|
30
|
+
(i) => x.isValidElement(i) && t(I(i), e)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function G(r, e, t) {
|
|
34
|
+
const i = new Set(e.map(String)), o = (c) => i.has(String(c)), s = [...r].filter((c) => !o(c)), a = t === "all" ? e : [...t].filter(o);
|
|
35
|
+
return /* @__PURE__ */ new Set([...s, ...a]);
|
|
36
|
+
}
|
|
37
|
+
function J(r, e) {
|
|
38
|
+
const t = new Set([...e].map(String)), i = [];
|
|
39
|
+
return R(r, (o) => {
|
|
40
|
+
t.has(String(w(o))) && i.push(I(o));
|
|
31
41
|
}), i.join(", ");
|
|
32
42
|
}
|
|
33
|
-
function
|
|
34
|
-
|
|
43
|
+
function Q({
|
|
44
|
+
children: r,
|
|
45
|
+
selectedKeys: e,
|
|
46
|
+
onSelectionChange: t,
|
|
47
|
+
disallowEmptySelection: i,
|
|
48
|
+
listLabel: o,
|
|
49
|
+
searchPlaceholder: s,
|
|
50
|
+
emptyStateText: a
|
|
51
|
+
}) {
|
|
52
|
+
const { contains: c } = j({ sensitivity: "base" }), [h, y] = F(""), m = N(null), l = $(r, h, c), f = l.map(w);
|
|
53
|
+
function b(d) {
|
|
54
|
+
var u, g;
|
|
55
|
+
d.key !== "ArrowDown" || l.length === 0 || (d.preventDefault(), (g = (u = m.current) == null ? void 0 : u.querySelector('[role="listbox"]')) == null || g.focus());
|
|
56
|
+
}
|
|
57
|
+
return /* @__PURE__ */ S("div", { ref: m, className: "select-search-panel", children: [
|
|
58
|
+
/* @__PURE__ */ n(
|
|
59
|
+
A,
|
|
60
|
+
{
|
|
61
|
+
"aria-label": s,
|
|
62
|
+
value: h,
|
|
63
|
+
onChange: y,
|
|
64
|
+
autoFocus: !0,
|
|
65
|
+
children: /* @__PURE__ */ n(
|
|
66
|
+
U,
|
|
67
|
+
{
|
|
68
|
+
className: "select-search-input",
|
|
69
|
+
placeholder: s,
|
|
70
|
+
onKeyDown: b
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
/* @__PURE__ */ n(
|
|
76
|
+
E,
|
|
77
|
+
{
|
|
78
|
+
"aria-label": o,
|
|
79
|
+
selectionMode: "multiple",
|
|
80
|
+
escapeKeyBehavior: "none",
|
|
81
|
+
disallowEmptySelection: i,
|
|
82
|
+
selectedKeys: e,
|
|
83
|
+
onSelectionChange: (d) => t(G(e, f, d)),
|
|
84
|
+
renderEmptyState: () => /* @__PURE__ */ n("span", { className: "select-empty-state", children: a }),
|
|
85
|
+
children: l
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] });
|
|
89
|
+
}
|
|
90
|
+
function ce({
|
|
91
|
+
className: r,
|
|
35
92
|
label: e,
|
|
36
|
-
description:
|
|
93
|
+
description: t,
|
|
37
94
|
errorMessage: i,
|
|
38
|
-
placeholder:
|
|
39
|
-
children:
|
|
40
|
-
selectedKeys:
|
|
41
|
-
onSelectionChange:
|
|
42
|
-
isDisabled:
|
|
95
|
+
placeholder: o,
|
|
96
|
+
children: s,
|
|
97
|
+
selectedKeys: a,
|
|
98
|
+
onSelectionChange: c,
|
|
99
|
+
isDisabled: h,
|
|
43
100
|
isInvalid: y,
|
|
44
|
-
disallowEmptySelection:
|
|
45
|
-
"aria-label":
|
|
101
|
+
disallowEmptySelection: m,
|
|
102
|
+
"aria-label": l,
|
|
103
|
+
...f
|
|
46
104
|
}) {
|
|
47
|
-
const
|
|
48
|
-
|
|
105
|
+
const b = D(r, "select-container"), d = z(), u = N(null), [g, B] = F(), T = k(() => {
|
|
106
|
+
u.current && B(`${u.current.offsetWidth}px`);
|
|
49
107
|
}, []);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
54
|
-
const
|
|
55
|
-
return
|
|
56
|
-
}, [
|
|
57
|
-
const
|
|
58
|
-
return /* @__PURE__ */ n("div", { className:
|
|
59
|
-
e && /* @__PURE__ */ n(
|
|
60
|
-
/* @__PURE__ */
|
|
61
|
-
/* @__PURE__ */
|
|
62
|
-
|
|
108
|
+
L(() => {
|
|
109
|
+
T();
|
|
110
|
+
const p = u.current;
|
|
111
|
+
if (!p || typeof ResizeObserver > "u") return;
|
|
112
|
+
const C = new ResizeObserver(T);
|
|
113
|
+
return C.observe(p), () => C.disconnect();
|
|
114
|
+
}, [T]);
|
|
115
|
+
const v = J(s, a);
|
|
116
|
+
return /* @__PURE__ */ n("div", { className: b, children: /* @__PURE__ */ S(K, { children: [
|
|
117
|
+
e && /* @__PURE__ */ n(q, { children: e }),
|
|
118
|
+
/* @__PURE__ */ S(M, { children: [
|
|
119
|
+
/* @__PURE__ */ S(
|
|
120
|
+
O,
|
|
63
121
|
{
|
|
64
|
-
ref:
|
|
122
|
+
ref: u,
|
|
65
123
|
className: "select",
|
|
66
|
-
"aria-label":
|
|
67
|
-
isDisabled:
|
|
124
|
+
"aria-label": l,
|
|
125
|
+
isDisabled: h,
|
|
68
126
|
"data-invalid": y || void 0,
|
|
69
127
|
children: [
|
|
70
128
|
/* @__PURE__ */ n(
|
|
71
129
|
"span",
|
|
72
130
|
{
|
|
73
131
|
className: "select-value",
|
|
74
|
-
"data-placeholder":
|
|
75
|
-
title:
|
|
76
|
-
children:
|
|
132
|
+
"data-placeholder": v === "" || void 0,
|
|
133
|
+
title: v || void 0,
|
|
134
|
+
children: v === "" ? o : v
|
|
77
135
|
}
|
|
78
136
|
),
|
|
79
|
-
/* @__PURE__ */ n(
|
|
137
|
+
/* @__PURE__ */ n(W, { "aria-hidden": "true" })
|
|
80
138
|
]
|
|
81
139
|
}
|
|
82
140
|
),
|
|
83
141
|
/* @__PURE__ */ n(
|
|
84
|
-
|
|
142
|
+
V,
|
|
85
143
|
{
|
|
86
144
|
className: "select-popover",
|
|
87
|
-
style: { "--trigger-width":
|
|
88
|
-
UNSTABLE_portalContainer:
|
|
89
|
-
children: /* @__PURE__ */ n(
|
|
90
|
-
|
|
145
|
+
style: { "--trigger-width": g },
|
|
146
|
+
UNSTABLE_portalContainer: d,
|
|
147
|
+
children: f.isSearchable ? /* @__PURE__ */ n(
|
|
148
|
+
Q,
|
|
149
|
+
{
|
|
150
|
+
listLabel: e ?? l,
|
|
151
|
+
selectedKeys: a,
|
|
152
|
+
onSelectionChange: c,
|
|
153
|
+
disallowEmptySelection: m,
|
|
154
|
+
searchPlaceholder: f.searchPlaceholder,
|
|
155
|
+
emptyStateText: f.emptyStateText,
|
|
156
|
+
children: s
|
|
157
|
+
}
|
|
158
|
+
) : /* @__PURE__ */ n(
|
|
159
|
+
E,
|
|
91
160
|
{
|
|
92
|
-
"aria-label": e ??
|
|
161
|
+
"aria-label": e ?? l,
|
|
93
162
|
autoFocus: !0,
|
|
94
163
|
selectionMode: "multiple",
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
164
|
+
escapeKeyBehavior: "none",
|
|
165
|
+
disallowEmptySelection: m,
|
|
166
|
+
selectedKeys: a,
|
|
167
|
+
onSelectionChange: (p) => c(
|
|
168
|
+
p === "all" ? _(s) : new Set(p)
|
|
99
169
|
),
|
|
100
|
-
children:
|
|
170
|
+
children: s
|
|
101
171
|
}
|
|
102
172
|
)
|
|
103
173
|
}
|
|
104
174
|
)
|
|
105
175
|
] }),
|
|
106
|
-
|
|
176
|
+
t && /* @__PURE__ */ n(H, { children: t }),
|
|
107
177
|
/* @__PURE__ */ n(P, { children: i })
|
|
108
178
|
] }) });
|
|
109
179
|
}
|
|
110
180
|
export {
|
|
111
|
-
|
|
181
|
+
ce as MultiSelectField
|
|
112
182
|
};
|
|
113
183
|
//# sourceMappingURL=MultiSelect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): string {\n const { id } = item.props as { id?: RACKey };\n return String(id ?? item.key ?? \"\");\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(itemKey(item))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\nexport interface MultiSelectFieldProps extends SharedFieldProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n disallowEmptySelection?: boolean;\n \"aria-label\"?: string;\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","selectedItemsText","selectedKeys","selected","texts","MultiSelectField","className","label","description","errorMessage","placeholder","onSelectionChange","isDisabled","isInvalid","disallowEmptySelection","ariaLabel","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","useRef","triggerWidth","setTriggerWidth","useState","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","jsx","Field","Label","RACMenuTrigger","jsxs","RACButton","IconChevronDown","RACPopover","ListBox","Description","FieldError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MultiSelect.js","sources":["../../../../../src/ui/primitives/Select/MultiSelect.tsx"],"sourcesContent":["import { clsx } from \"clsx\";\nimport { useOverlayPortalContainer } from \"hooks\";\nimport { IconChevronDown } from \"icons\";\nimport {\n Description,\n Field,\n FieldError,\n Input,\n Label,\n ListBox,\n SharedFieldProps,\n} from \"primitives\";\nimport React, { useCallback, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n Button as RACButton,\n MenuTrigger as RACMenuTrigger,\n Popover as RACPopover,\n TextField as RACTextField,\n useFilter,\n type Key as RACKey,\n type Selection as RACSelection,\n} from \"react-aria-components\";\nimport \"./select.css\";\n\nfunction itemKey(item: React.ReactElement): RACKey {\n const { id } = item.props as { id?: RACKey };\n return id ?? item.key ?? \"\";\n}\n\nfunction itemText(item: React.ReactElement): string {\n const { textValue, children } = item.props as {\n textValue?: string;\n children?: React.ReactNode;\n };\n if (textValue !== undefined) return textValue;\n return typeof children === \"string\" ? children : \"\";\n}\n\nfunction forEachItem(\n children: React.ReactNode,\n visit: (item: React.ReactElement) => void,\n) {\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child)) visit(child);\n });\n}\n\nfunction allItemKeys(children: React.ReactNode): Set<RACKey> {\n const keys = new Set<RACKey>();\n forEachItem(children, (item) => keys.add(itemKey(item)));\n return keys;\n}\n\ntype TextMatcher = (text: string, searchText: string) => boolean;\n\nfunction matchingItems(\n children: React.ReactNode,\n searchText: string,\n matches: TextMatcher,\n): React.ReactElement[] {\n return React.Children.toArray(children).filter(\n (child): child is React.ReactElement =>\n React.isValidElement(child) && matches(itemText(child), searchText),\n );\n}\n\nfunction keepHiddenSelection(\n previousKeys: Iterable<RACKey>,\n visibleKeys: RACKey[],\n visibleSelection: RACSelection,\n): Set<RACKey> {\n const visible = new Set(visibleKeys.map(String));\n const isVisible = (key: RACKey) => visible.has(String(key));\n const hiddenSelected = [...previousKeys].filter((key) => !isVisible(key));\n const visibleSelected =\n visibleSelection === \"all\"\n ? visibleKeys\n : [...visibleSelection].filter(isVisible);\n return new Set([...hiddenSelected, ...visibleSelected]);\n}\n\nfunction selectedItemsText(\n children: React.ReactNode,\n selectedKeys: Iterable<RACKey>,\n): string {\n const selected = new Set([...selectedKeys].map(String));\n const texts: string[] = [];\n forEachItem(children, (item) => {\n if (selected.has(String(itemKey(item)))) texts.push(itemText(item));\n });\n return texts.join(\", \");\n}\n\ninterface MultiSelectOptionsProps {\n children: React.ReactNode;\n selectedKeys: Iterable<RACKey>;\n onSelectionChange: (keys: Set<RACKey>) => void;\n disallowEmptySelection?: boolean;\n}\n\ninterface MultiSelectFieldBaseProps\n extends SharedFieldProps,\n MultiSelectOptionsProps {\n className?: string;\n isDisabled?: boolean;\n isInvalid?: boolean;\n \"aria-label\"?: string;\n}\n\nexport interface MultiSelectSearchProps {\n isSearchable: true;\n searchPlaceholder: string;\n emptyStateText: string;\n}\n\ninterface MultiSelectWithoutSearchProps {\n isSearchable?: false;\n searchPlaceholder?: never;\n emptyStateText?: never;\n}\n\nexport type MultiSelectFieldProps = MultiSelectFieldBaseProps &\n (MultiSelectSearchProps | MultiSelectWithoutSearchProps);\n\nfunction SearchableOptions({\n children,\n selectedKeys,\n onSelectionChange,\n disallowEmptySelection,\n listLabel,\n searchPlaceholder,\n emptyStateText,\n}: MultiSelectOptionsProps &\n Omit<MultiSelectSearchProps, \"isSearchable\"> & { listLabel?: string }) {\n const { contains } = useFilter({ sensitivity: \"base\" });\n const [searchText, setSearchText] = useState(\"\");\n const panelRef = useRef<HTMLDivElement>(null);\n const visibleItems = matchingItems(children, searchText, contains);\n const visibleKeys = visibleItems.map(itemKey);\n\n function moveFocusToList(event: React.KeyboardEvent<HTMLInputElement>) {\n if (event.key !== \"ArrowDown\" || visibleItems.length === 0) return;\n event.preventDefault();\n panelRef.current?.querySelector<HTMLElement>('[role=\"listbox\"]')?.focus();\n }\n\n return (\n <div ref={panelRef} className=\"select-search-panel\">\n <RACTextField\n aria-label={searchPlaceholder}\n value={searchText}\n onChange={setSearchText}\n autoFocus\n >\n <Input\n className=\"select-search-input\"\n placeholder={searchPlaceholder}\n onKeyDown={moveFocusToList}\n />\n </RACTextField>\n <ListBox\n aria-label={listLabel}\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(keepHiddenSelection(selectedKeys, visibleKeys, keys))\n }\n renderEmptyState={() => (\n <span className=\"select-empty-state\">{emptyStateText}</span>\n )}\n >\n {visibleItems}\n </ListBox>\n </div>\n );\n}\n\nexport function MultiSelectField({\n className,\n label,\n description,\n errorMessage,\n placeholder,\n children,\n selectedKeys,\n onSelectionChange,\n isDisabled,\n isInvalid,\n disallowEmptySelection,\n \"aria-label\": ariaLabel,\n ...searchProps\n}: MultiSelectFieldProps) {\n const classNames = clsx(className, \"select-container\");\n const portalContainer = useOverlayPortalContainer();\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [triggerWidth, setTriggerWidth] = useState<string>();\n\n const measureTrigger = useCallback(() => {\n if (triggerRef.current) {\n setTriggerWidth(`${triggerRef.current.offsetWidth}px`);\n }\n }, []);\n\n useLayoutEffect(() => {\n measureTrigger();\n const trigger = triggerRef.current;\n if (!trigger || typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(measureTrigger);\n observer.observe(trigger);\n return () => observer.disconnect();\n }, [measureTrigger]);\n\n const chosenText = selectedItemsText(children, selectedKeys);\n\n return (\n <div className={classNames}>\n <Field>\n {label && <Label>{label}</Label>}\n <RACMenuTrigger>\n <RACButton\n ref={triggerRef}\n className=\"select\"\n aria-label={ariaLabel}\n isDisabled={isDisabled}\n data-invalid={isInvalid || undefined}\n >\n <span\n className=\"select-value\"\n data-placeholder={chosenText === \"\" || undefined}\n title={chosenText || undefined}\n >\n {chosenText === \"\" ? placeholder : chosenText}\n </span>\n <IconChevronDown aria-hidden=\"true\" />\n </RACButton>\n <RACPopover\n className=\"select-popover\"\n style={{ \"--trigger-width\": triggerWidth } as React.CSSProperties}\n UNSTABLE_portalContainer={portalContainer}\n >\n {searchProps.isSearchable ? (\n <SearchableOptions\n listLabel={label ?? ariaLabel}\n selectedKeys={selectedKeys}\n onSelectionChange={onSelectionChange}\n disallowEmptySelection={disallowEmptySelection}\n searchPlaceholder={searchProps.searchPlaceholder}\n emptyStateText={searchProps.emptyStateText}\n >\n {children}\n </SearchableOptions>\n ) : (\n <ListBox\n aria-label={label ?? ariaLabel}\n autoFocus\n selectionMode=\"multiple\"\n escapeKeyBehavior=\"none\"\n disallowEmptySelection={disallowEmptySelection}\n selectedKeys={selectedKeys}\n onSelectionChange={(keys: RACSelection) =>\n onSelectionChange(\n keys === \"all\" ? allItemKeys(children) : new Set(keys),\n )\n }\n >\n {children}\n </ListBox>\n )}\n </RACPopover>\n </RACMenuTrigger>\n {description && <Description>{description}</Description>}\n <FieldError>{errorMessage}</FieldError>\n </Field>\n </div>\n );\n}\n"],"names":["itemKey","item","id","itemText","textValue","children","forEachItem","visit","React","child","allItemKeys","keys","matchingItems","searchText","matches","keepHiddenSelection","previousKeys","visibleKeys","visibleSelection","visible","isVisible","key","hiddenSelected","visibleSelected","selectedItemsText","selectedKeys","selected","texts","SearchableOptions","onSelectionChange","disallowEmptySelection","listLabel","searchPlaceholder","emptyStateText","contains","useFilter","setSearchText","useState","panelRef","useRef","visibleItems","moveFocusToList","event","_b","_a","jsxs","jsx","RACTextField","Input","ListBox","MultiSelectField","className","label","description","errorMessage","placeholder","isDisabled","isInvalid","ariaLabel","searchProps","classNames","clsx","portalContainer","useOverlayPortalContainer","triggerRef","triggerWidth","setTriggerWidth","measureTrigger","useCallback","useLayoutEffect","trigger","observer","chosenText","Field","Label","RACMenuTrigger","RACButton","IconChevronDown","RACPopover","Description","FieldError"],"mappings":"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"}
|
|
@@ -2,14 +2,28 @@ import { SharedFieldProps } from "primitives";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { type Key as RACKey } from "react-aria-components";
|
|
4
4
|
import "./select.css";
|
|
5
|
-
|
|
5
|
+
interface MultiSelectOptionsProps {
|
|
6
6
|
children: React.ReactNode;
|
|
7
7
|
selectedKeys: Iterable<RACKey>;
|
|
8
8
|
onSelectionChange: (keys: Set<RACKey>) => void;
|
|
9
|
+
disallowEmptySelection?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface MultiSelectFieldBaseProps extends SharedFieldProps, MultiSelectOptionsProps {
|
|
9
12
|
className?: string;
|
|
10
13
|
isDisabled?: boolean;
|
|
11
14
|
isInvalid?: boolean;
|
|
12
|
-
disallowEmptySelection?: boolean;
|
|
13
15
|
"aria-label"?: string;
|
|
14
16
|
}
|
|
15
|
-
export
|
|
17
|
+
export interface MultiSelectSearchProps {
|
|
18
|
+
isSearchable: true;
|
|
19
|
+
searchPlaceholder: string;
|
|
20
|
+
emptyStateText: string;
|
|
21
|
+
}
|
|
22
|
+
interface MultiSelectWithoutSearchProps {
|
|
23
|
+
isSearchable?: false;
|
|
24
|
+
searchPlaceholder?: never;
|
|
25
|
+
emptyStateText?: never;
|
|
26
|
+
}
|
|
27
|
+
export type MultiSelectFieldProps = MultiSelectFieldBaseProps & (MultiSelectSearchProps | MultiSelectWithoutSearchProps);
|
|
28
|
+
export declare function MultiSelectField({ className, label, description, errorMessage, placeholder, children, selectedKeys, onSelectionChange, isDisabled, isInvalid, disallowEmptySelection, "aria-label": ariaLabel, ...searchProps }: MultiSelectFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apipass/design-system",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "APIPass React Design System",
|
|
6
6
|
"sideEffects": [
|
|
@@ -135,6 +135,9 @@
|
|
|
135
135
|
"@storybook/addon-mcp": "^0.5.0",
|
|
136
136
|
"@storybook/react": "^10.3.4",
|
|
137
137
|
"@storybook/react-vite": "^10.3.4",
|
|
138
|
+
"@testing-library/dom": "^10.4.0",
|
|
139
|
+
"@testing-library/react": "^16.3.0",
|
|
140
|
+
"@testing-library/user-event": "^14.6.1",
|
|
138
141
|
"@types/react": "^18.2.15",
|
|
139
142
|
"@types/react-dom": "^18.2.7",
|
|
140
143
|
"@types/react-grid-layout": "^1.3.6",
|
|
@@ -146,6 +149,7 @@
|
|
|
146
149
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
147
150
|
"eslint-plugin-react-refresh": "^0.4.3",
|
|
148
151
|
"eslint-plugin-storybook": "^10.3.4",
|
|
152
|
+
"jsdom": "^26.1.0",
|
|
149
153
|
"postcss": "8.5.6",
|
|
150
154
|
"prettier-plugin-organize-imports": "^3.2.4",
|
|
151
155
|
"react": "^18.2.0",
|