@lifesg/react-design-system 3.5.0-canary.2 → 3.5.0-canary.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.
Files changed (33) hide show
  1. package/cjs/data-table/data-table.js +1 -1
  2. package/cjs/data-table/data-table.js.map +1 -1
  3. package/cjs/data-table/data-table.styles.js +61 -52
  4. package/cjs/data-table/data-table.styles.js.map +1 -1
  5. package/cjs/external/dompurify/dist/purify.es.js +2 -2
  6. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  7. package/cjs/predictive-text-input/predictive-text-input.js +1 -1
  8. package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
  9. package/cjs/shared/dropdown-wrapper/element-with-dropdown.js +1 -1
  10. package/cjs/shared/dropdown-wrapper/element-with-dropdown.js.map +1 -1
  11. package/cjs/table/table.styles.js +4 -6
  12. package/cjs/table/table.styles.js.map +1 -1
  13. package/cjs/util/use-throttle.js +2 -0
  14. package/cjs/util/use-throttle.js.map +1 -0
  15. package/data-table/data-table.js +1 -1
  16. package/data-table/data-table.js.map +1 -1
  17. package/data-table/data-table.styles.d.ts +11 -11
  18. package/data-table/data-table.styles.js +73 -64
  19. package/data-table/data-table.styles.js.map +1 -1
  20. package/external/dompurify/dist/purify.es.js +2 -2
  21. package/external/dompurify/dist/purify.es.js.map +1 -1
  22. package/package.json +1 -1
  23. package/predictive-text-input/predictive-text-input.js +1 -1
  24. package/predictive-text-input/predictive-text-input.js.map +1 -1
  25. package/shared/dropdown-wrapper/element-with-dropdown.d.ts +5 -4
  26. package/shared/dropdown-wrapper/element-with-dropdown.js +1 -1
  27. package/shared/dropdown-wrapper/element-with-dropdown.js.map +1 -1
  28. package/table/table.styles.js +10 -12
  29. package/table/table.styles.js.map +1 -1
  30. package/util/index.d.ts +1 -0
  31. package/util/use-throttle.d.ts +1 -0
  32. package/util/use-throttle.js +2 -0
  33. package/util/use-throttle.js.map +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifesg/react-design-system",
3
- "version": "3.5.0-canary.2",
3
+ "version": "3.5.0-canary.3",
4
4
  "description": "A component design system for LifeSG web apps",
5
5
  "keywords": [
6
6
  "design-system"
@@ -1,2 +1,2 @@
1
- import{__rest as e,__awaiter as t}from"../_virtual/_tslib.js";import{jsx as r,Fragment as o,jsxs as i}from"react/jsx-runtime";import s from"../external/lodash/debounce.js";import{useState as l,useRef as a,useCallback as n,useEffect as d}from"react";import{VisuallyHidden as p,concatIds as c}from"../shared/accessibility/index.js";import{Input as m}from"../input/input.js";import"styled-components";import"../theme/index.js";import"../util/string-helper.js";import"../shared/dropdown-list/dropdown-label.styles.js";import{DropdownList as u}from"../shared/dropdown-list/dropdown-list.js";import{DropdownListState as h}from"../shared/dropdown-list/dropdown-list-state.js";import"../shared/dropdown-list/expandable-element.js";import"@lifesg/react-icons/caret-right";import"react-virtuoso";import"../button/button.style.js";import"../util/calendar-helper.js";import"../util/date-helper.js";import"../util/date-input-helper.js";import{useId as g}from"../util/simple-id-generator.js";import"@react-aria/live-announcer";import{ElementWithDropdown as f}from"../shared/dropdown-wrapper/element-with-dropdown.js";import"../shared/dropdown-list/dropdown-list.styles.js";import"../shared/dropdown-list/dropdown-search.js";import"immer";import"../external/lodash/_getTag.js";import"../external/lodash/isArguments.js";import"../external/lodash/_baseGetTag.js";import"../external/lodash/isBuffer.js";import"../external/lodash/isTypedArray.js";import"../external/lodash/_Stack.js";import"../external/lodash/_SetCache.js";import"../external/lodash/_equalByTag.js";import"../shared/dropdown-list/nested-dropdown-list.styles.js";import"../shared/dropdown-list/virtuoso-components.js";import{InputWrapper as x}from"../shared/input-wrapper/input-wrapper.js";const j=j=>{var{className:w,"data-testid":b,selectedOption:y,minimumCharacters:v=3,fetchOptions:O,placeholder:T="Enter here...",readOnly:E=!1,disabled:I=!1,error:S,valueExtractor:C,listExtractor:N,displayValueExtractor:$,onSelectOption:_,alignment:B,dropdownZIndex:D,dropdownRootNode:A,dropdownWidth:L,"aria-describedby":R}=j,W=e(j,["className","data-testid","selectedOption","minimumCharacters","fetchOptions","placeholder","readOnly","disabled","error","valueExtractor","listExtractor","displayValueExtractor","onSelectOption","alignment","dropdownZIndex","dropdownRootNode","dropdownWidth","aria-describedby"]);const Z=e=>e?$?$(e):e.toString():"",[k,F]=l((()=>y?Z(y):"")),[V,q]=l((()=>y?Z(y):"")),[G,H]=l([]),[M,P]=l(!0),[z,J]=l(!1),[K,Q]=l(!!y),[U,X]=l(y),[Y,ee]=l(!1),[te,re]=l(!1),oe=g(),[ie,se]=l(null),le=`${oe}-instruction`,ae=a(null),ne=a(null),de=a(O),pe=n((e=>t(void 0,void 0,void 0,(function*(){if(de.current){J(!1),P(!0);try{const t=yield de.current(e);q(e),H(null!=t?t:[]),P(!1)}catch(e){J(!0),P(!1)}}}))),[]),ce=n(s((e=>{pe(e)}),500),[pe]);d((()=>{de.current=O}),[O]),d((()=>{k&&k.length>=v?K?k!==V&&ce(k):(ee(!0),ce(k)):ce.cancel(),""===k&&U&&(null==_||_(void 0,void 0),we(),X(void 0)),y&&k!==Z(y)&&Q(!1)}),[k,y]),d((()=>{F(y?Z(y):""),q(y?Z(y):""),X(y),H([]),Q(!!y)}),[y]),d((()=>{var e;const t=be(),r=null!==(e=null==G?void 0:G.length)&&void 0!==e?e:0;"loading"===t&&k.length>=v?se("Loading suggested results"):"fail"!==t?!Y||M||z||se(0===r?k?"No results found.":null:`${r} result${r>1?"s":""} found. Press down arrow to scroll through the list.`):se("Suggestions failed to load. Try again.")}),[G,k,z,M]),d((()=>()=>{ce.cancel()}),[ce]);const me=(e,t)=>{var r;null===(r=ne.current)||void 0===r||r.focus(),F(Z(e)),q(e?Z(e):""),Q(!0),X(e),ee(!1),null==_||_(e,t)},ue=()=>{re(!0)},he=e=>{Y||!ae.current||ae.current.contains(e.relatedTarget)||(re(!1),xe())},ge=()=>{ee(!1),re(!1)},fe=()=>{F(""),H([]),Q(!1),ee(!1),null==_||_(void 0,void 0)},xe=()=>{if(!K)if(U){const e=Z(U);F(e),ee(!1)}else fe()},je=e=>{F(e.target.value),Q(!1)},we=e=>{q(""),Q(!1),H([]),P(!0)},be=()=>z?"fail":M?"loading":"success";return r(h,{children:r(f,{enabled:!E&&!I,isOpen:Y,renderElement:()=>i(x,{className:w,"data-testid":b,ref:ae,tabIndex:-1,onFocus:ue,onBlur:he,$focused:te,$disabled:I,$readOnly:E,$error:S,children:[i(p,{id:le,"aria-hidden":!0,children:["Type in ",v," or more characters for suggested results."]}),ie&&r(p,{"aria-live":"polite",children:ie}),r(m,Object.assign({role:"combobox",ref:ne,id:oe,type:"text",value:k,onChange:je,placeholder:T,readOnly:E,disabled:I,allowClear:!0,onClear:fe,"aria-expanded":Y,"aria-controls":oe,"aria-autocomplete":"list","aria-haspopup":"listbox",onBlur:k.length<v?xe:void 0,styleType:"no-border","aria-describedby":c(R,le)},W))]}),renderDropdown:()=>r(o,{children:r(u,{listboxId:oe,listItems:G,onSelectItem:me,onDismiss:ge,valueExtractor:C,listExtractor:N,itemsLoadState:be(),itemTruncationType:"end",itemMaxLines:1,labelDisplayType:"next-line",disableItemFocus:!0,onRetry:()=>pe(k),width:L,matchElementWidth:!0})}),onOpen:()=>{!K&&k.length>=v&&re(!0)},onClose:()=>{ee(!1),re(!1),xe()},onDismiss:()=>{var e;ee(!1),re(!1),xe(),null===(e=ne.current)||void 0===e||e.focus()},clickToToggle:!1,offset:8,alignment:B,fitAvailableHeight:!0,customZIndex:D,rootNode:A})})};export{j as PredictiveTextInput};
1
+ import{__rest as e,__awaiter as t}from"../_virtual/_tslib.js";import{jsx as r,jsxs as o}from"react/jsx-runtime";import i from"../external/lodash/debounce.js";import{useState as s,useRef as l,useCallback as a,useEffect as n}from"react";import{VisuallyHidden as d,concatIds as p}from"../shared/accessibility/index.js";import{Input as c}from"../input/input.js";import"styled-components";import"../theme/index.js";import"../util/string-helper.js";import"../shared/dropdown-list/dropdown-label.styles.js";import{DropdownList as m}from"../shared/dropdown-list/dropdown-list.js";import{DropdownListState as u}from"../shared/dropdown-list/dropdown-list-state.js";import"../shared/dropdown-list/expandable-element.js";import"@lifesg/react-icons/caret-right";import"react-virtuoso";import"../button/button.style.js";import"../util/calendar-helper.js";import"../util/date-helper.js";import"../util/date-input-helper.js";import{useId as h}from"../util/simple-id-generator.js";import"@react-aria/live-announcer";import{ElementWithDropdown as g}from"../shared/dropdown-wrapper/element-with-dropdown.js";import"../shared/dropdown-list/dropdown-list.styles.js";import"../shared/dropdown-list/dropdown-search.js";import"immer";import"../external/lodash/_getTag.js";import"../external/lodash/isArguments.js";import"../external/lodash/_baseGetTag.js";import"../external/lodash/isBuffer.js";import"../external/lodash/isTypedArray.js";import"../external/lodash/_Stack.js";import"../external/lodash/_SetCache.js";import"../external/lodash/_equalByTag.js";import"../shared/dropdown-list/nested-dropdown-list.styles.js";import"../shared/dropdown-list/virtuoso-components.js";import{InputWrapper as f}from"../shared/input-wrapper/input-wrapper.js";const x=x=>{var{className:j,"data-testid":w,selectedOption:b,minimumCharacters:y=3,fetchOptions:v,placeholder:O="Enter here...",readOnly:T=!1,disabled:E=!1,error:I,valueExtractor:S,listExtractor:C,displayValueExtractor:N,onSelectOption:$,alignment:_,dropdownZIndex:B,dropdownRootNode:D,dropdownWidth:A,"aria-describedby":L}=x,R=e(x,["className","data-testid","selectedOption","minimumCharacters","fetchOptions","placeholder","readOnly","disabled","error","valueExtractor","listExtractor","displayValueExtractor","onSelectOption","alignment","dropdownZIndex","dropdownRootNode","dropdownWidth","aria-describedby"]);const W=e=>e?N?N(e):e.toString():"",[Z,k]=s((()=>b?W(b):"")),[F,H]=s((()=>b?W(b):"")),[V,q]=s([]),[G,M]=s(!0),[P,z]=s(!1),[J,K]=s(!!b),[Q,U]=s(b),[X,Y]=s(!1),[ee,te]=s(!1),re=h(),[oe,ie]=s(null),se=`${re}-instruction`,le=l(null),ae=l(null),ne=l(v),de=a((e=>t(void 0,void 0,void 0,(function*(){if(ne.current){z(!1),M(!0);try{const t=yield ne.current(e);H(e),q(null!=t?t:[]),M(!1)}catch(e){z(!0),M(!1)}}}))),[]),pe=a(i((e=>{de(e)}),500),[de]);n((()=>{ne.current=v}),[v]),n((()=>{Z&&Z.length>=y?J?Z!==F&&pe(Z):(Y(!0),pe(Z)):pe.cancel(),""===Z&&Q&&(null==$||$(void 0,void 0),je(),U(void 0)),b&&Z!==W(b)&&K(!1)}),[Z,b]),n((()=>{k(b?W(b):""),H(b?W(b):""),U(b),K(!!b)}),[b]),n((()=>{var e;const t=we(),r=null!==(e=null==V?void 0:V.length)&&void 0!==e?e:0;"loading"===t&&Z.length>=y?ie("Loading suggested results"):"fail"!==t?!X||G||P||ie(0===r?Z?"No results found.":null:`${r} result${r>1?"s":""} found. Press down arrow to scroll through the list.`):ie("Suggestions failed to load. Try again.")}),[V,Z,P,G]),n((()=>()=>{pe.cancel()}),[pe]);const ce=(e,t)=>{var r;null===(r=ae.current)||void 0===r||r.focus(),k(W(e)),H(e?W(e):""),K(!0),U(e),Y(!1),null==$||$(e,t)},me=()=>{te(!0)},ue=e=>{X||!le.current||le.current.contains(e.relatedTarget)||(te(!1),fe())},he=()=>{Y(!1),te(!1)},ge=()=>{k(""),K(!1),Y(!1),null==$||$(void 0,void 0)},fe=()=>{if(!J)if(Q){const e=W(Q);k(e),Y(!1)}else ge()},xe=e=>{k(e.target.value),K(!1)},je=e=>{H(""),K(!1),M(!0)},we=()=>P?"fail":G?"loading":"success";return r(u,{children:r(g,{enabled:!T&&!E,isOpen:X,renderElement:()=>o(f,{className:j,"data-testid":w,ref:le,tabIndex:-1,onFocus:me,onBlur:ue,$focused:ee,$disabled:E,$readOnly:T,$error:I,children:[o(d,{id:se,"aria-hidden":!0,children:["Type in ",y," or more characters for suggested results."]}),oe&&r(d,{"aria-live":"polite",children:oe}),r(c,Object.assign({role:"combobox",ref:ae,id:re,type:"text",value:Z,onChange:xe,placeholder:O,readOnly:T,disabled:E,allowClear:!0,onClear:ge,"aria-expanded":X,"aria-controls":re,"aria-autocomplete":"list","aria-haspopup":"listbox",onBlur:Z.length<y?fe:void 0,styleType:"no-border","aria-describedby":p(L,se)},R))]}),renderDropdown:()=>r(m,{listboxId:re,listItems:V,onSelectItem:ce,onDismiss:he,valueExtractor:S,listExtractor:C,itemsLoadState:we(),itemTruncationType:"end",itemMaxLines:1,labelDisplayType:"next-line",disableItemFocus:!0,onRetry:()=>de(Z),width:A,matchElementWidth:!0}),onOpen:()=>{!J&&Z.length>=y&&te(!0)},onClose:()=>{Y(!1),te(!1),fe()},onDismiss:()=>{var e;Y(!1),te(!1),fe(),null===(e=ae.current)||void 0===e||e.focus()},onHide:()=>{q([]),M(!0),z(!1)},clickToToggle:!1,offset:8,alignment:_,fitAvailableHeight:!0,customZIndex:B,rootNode:D})})};export{x as PredictiveTextInput};
2
2
  //# sourceMappingURL=predictive-text-input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"predictive-text-input.js","sources":["../../src/predictive-text-input/predictive-text-input.tsx"],"sourcesContent":["import debounce from \"lodash/debounce\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { VisuallyHidden, concatIds } from \"src/shared/accessibility\";\nimport { Input } from \"../input\";\nimport { DropdownList, DropdownListState } from \"../shared/dropdown-list\";\nimport { ItemsLoadStateType } from \"../shared/dropdown-list/types\";\nimport { ElementWithDropdown } from \"../shared/dropdown-wrapper\";\nimport { InputWrapper } from \"../shared/input-wrapper/input-wrapper\";\nimport { useId } from \"../util\";\nimport { PredictiveTextInputProps } from \"./types\";\n\nexport const PredictiveTextInput = <T, V>({\n className,\n \"data-testid\": testId,\n selectedOption,\n minimumCharacters = 3,\n fetchOptions,\n placeholder = \"Enter here...\",\n readOnly = false,\n disabled = false,\n error,\n valueExtractor,\n listExtractor,\n displayValueExtractor,\n onSelectOption,\n alignment,\n dropdownZIndex,\n dropdownRootNode,\n dropdownWidth,\n \"aria-describedby\": ariaDescribedBy,\n ...otherProps\n}: PredictiveTextInputProps<T, V>): JSX.Element => {\n const getDisplayValue = (item: T | undefined): string => {\n if (!item) return \"\";\n return displayValueExtractor\n ? displayValueExtractor(item)\n : item.toString();\n };\n\n // =============================================================================\n // CONST, STATE\n // =============================================================================\n const [input, setInput] = useState<string>(() =>\n selectedOption ? getDisplayValue(selectedOption) : \"\"\n );\n const [searchedInput, setSearchedInput] = useState<string>(() =>\n selectedOption ? getDisplayValue(selectedOption) : \"\"\n );\n const [options, setOptions] = useState<T[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [isError, setIsError] = useState<boolean>(false);\n const [isOptionSelected, setIsOptionSelected] = useState<boolean>(\n !!selectedOption\n );\n const [prevOptionSelected, setPrevOptionSelected] = useState<T | undefined>(\n selectedOption\n );\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const internalId = useId();\n const [resultAnnouncement, setResultAnnouncement] = useState<string | null>(\n null\n );\n const instructionId = `${internalId}-instruction`;\n\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const selectorRef = useRef<HTMLInputElement | null>(null);\n\n const fetchOptionsRef = useRef(fetchOptions);\n\n // =============================================================================\n // DEBOUNCE FUNCTIONS\n // =============================================================================\n const handleFetchOptions = useCallback(async (input: string) => {\n if (!fetchOptionsRef.current) return;\n setIsError(false);\n setIsLoading(true);\n try {\n const fetchedOptions = await fetchOptionsRef.current(input);\n setSearchedInput(input);\n setOptions(fetchedOptions ?? []);\n setIsLoading(false);\n } catch {\n setIsError(true);\n setIsLoading(false);\n }\n }, []);\n\n const fetchOptionsDebounced = useCallback(\n debounce((input: string) => {\n handleFetchOptions(input);\n }, 500),\n [handleFetchOptions]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n\n useEffect(() => {\n fetchOptionsRef.current = fetchOptions;\n }, [fetchOptions]);\n\n useEffect(() => {\n /***\n * Should not fetch options for the following the scenario :\n * 1. When input < minimumCharacters\n * 2. When user selected option from dropdown becomes input\n * 3. Initial selectedOption passed in as input\n */\n if (input && input.length >= minimumCharacters) {\n if (!isOptionSelected) {\n setIsOpen(true);\n fetchOptionsDebounced(input);\n } else if (input !== searchedInput) {\n fetchOptionsDebounced(input);\n }\n } else {\n fetchOptionsDebounced.cancel();\n }\n\n if (input === \"\" && prevOptionSelected) {\n onSelectOption?.(undefined, undefined);\n handleDropdownDismiss();\n setPrevOptionSelected(undefined);\n }\n\n if (selectedOption && input !== getDisplayValue(selectedOption)) {\n setIsOptionSelected(false);\n }\n }, [input, selectedOption]);\n\n useEffect(() => {\n setInput(selectedOption ? getDisplayValue(selectedOption) : \"\");\n setSearchedInput(selectedOption ? getDisplayValue(selectedOption) : \"\");\n setPrevOptionSelected(selectedOption);\n setOptions([]);\n setIsOptionSelected(!!selectedOption);\n }, [selectedOption]);\n\n useEffect(() => {\n const state = getItemsLoadState();\n const count = options?.length ?? 0;\n\n if (state === \"loading\" && input.length >= minimumCharacters) {\n setResultAnnouncement(\"Loading suggested results\");\n return;\n }\n\n if (state === \"fail\") {\n setResultAnnouncement(\"Suggestions failed to load. Try again.\");\n return;\n }\n\n if (isOpen && !isLoading && !isError) {\n if (count === 0) {\n setResultAnnouncement(input ? \"No results found.\" : null);\n } else {\n setResultAnnouncement(\n `${count} result${\n count > 1 ? \"s\" : \"\"\n } found. Press down arrow to scroll through the list.`\n );\n }\n }\n }, [options, input, isError, isLoading]);\n\n // =============================================================================\n // Cleanup: cancel debounce on unmount\n // =============================================================================\n useEffect(() => {\n return () => {\n fetchOptionsDebounced.cancel();\n };\n }, [fetchOptionsDebounced]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleListItemClick = (item: T, extractedValue: V) => {\n selectorRef.current?.focus();\n setInput(getDisplayValue(item));\n setSearchedInput(item ? getDisplayValue(item) : \"\");\n setIsOptionSelected(true);\n setPrevOptionSelected(item);\n setIsOpen(false);\n onSelectOption?.(item, extractedValue);\n };\n\n const handleOpen = () => {\n if (!isOptionSelected && input.length >= minimumCharacters) {\n setIsFocused(true);\n }\n };\n\n const handleClose = () => {\n setIsOpen(false);\n setIsFocused(false);\n handleOnBlur();\n };\n\n const handleNodeFocus = () => {\n setIsFocused(true);\n };\n\n const handleNodeBlur = (e: React.FocusEvent) => {\n if (\n !isOpen &&\n nodeRef.current &&\n !nodeRef.current.contains(e.relatedTarget as Node)\n ) {\n setIsFocused(false);\n handleOnBlur();\n }\n };\n\n const handleListDismiss = () => {\n setIsOpen(false);\n setIsFocused(false);\n };\n\n const handleDismiss = () => {\n setIsOpen(false);\n setIsFocused(false);\n handleOnBlur();\n selectorRef.current?.focus();\n };\n\n const handleOnClear = () => {\n setInput(\"\");\n setOptions([]);\n setIsOptionSelected(false);\n setIsOpen(false);\n onSelectOption?.(undefined, undefined);\n };\n\n const handleOnBlur = () => {\n if (!isOptionSelected) {\n if (prevOptionSelected) {\n const prevValue = getDisplayValue(prevOptionSelected);\n setInput(prevValue);\n setIsOpen(false);\n } else {\n handleOnClear();\n }\n }\n };\n\n const handleTyping = (e: React.ChangeEvent<HTMLInputElement>) => {\n setInput(e.target.value);\n setIsOptionSelected(false);\n };\n\n const handleDropdownDismiss = (item?: T) => {\n setSearchedInput(item ? getDisplayValue(item) : \"\");\n setIsOptionSelected(!!item);\n setOptions([]);\n setIsLoading(true);\n };\n\n // =============================================================================\n // HELPER FUNCTION\n // =============================================================================\n const getItemsLoadState = (): ItemsLoadStateType => {\n if (isError) return \"fail\";\n return isLoading ? \"loading\" : \"success\";\n };\n\n // =============================================================================\n // RENDER FUNCTION\n // =============================================================================\n const renderInputElement = () => {\n return (\n <InputWrapper\n className={className}\n data-testid={testId}\n ref={nodeRef}\n tabIndex={-1}\n onFocus={handleNodeFocus}\n onBlur={handleNodeBlur}\n $focused={isFocused}\n $disabled={disabled}\n $readOnly={readOnly}\n $error={error}\n >\n <VisuallyHidden id={instructionId} aria-hidden>\n Type in {minimumCharacters} or more characters for suggested\n results.\n </VisuallyHidden>\n {resultAnnouncement && (\n <VisuallyHidden aria-live=\"polite\">\n {resultAnnouncement}\n </VisuallyHidden>\n )}\n <Input\n role=\"combobox\"\n ref={selectorRef}\n id={internalId}\n type=\"text\"\n value={input}\n onChange={handleTyping}\n placeholder={placeholder}\n readOnly={readOnly}\n disabled={disabled}\n allowClear\n onClear={handleOnClear}\n aria-expanded={isOpen}\n aria-controls={internalId}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n onBlur={\n input.length < minimumCharacters\n ? handleOnBlur\n : undefined\n }\n styleType=\"no-border\"\n aria-describedby={concatIds(ariaDescribedBy, instructionId)}\n {...otherProps}\n />\n </InputWrapper>\n );\n };\n\n const renderDropdown = () => {\n return (\n <>\n <DropdownList\n listboxId={internalId}\n listItems={options}\n onSelectItem={handleListItemClick}\n onDismiss={handleListDismiss}\n valueExtractor={valueExtractor}\n listExtractor={listExtractor}\n itemsLoadState={getItemsLoadState()}\n itemTruncationType={\"end\"}\n itemMaxLines={1}\n labelDisplayType={\"next-line\"}\n disableItemFocus\n onRetry={() => handleFetchOptions(input)}\n width={dropdownWidth}\n matchElementWidth\n />\n </>\n );\n };\n\n return (\n <DropdownListState>\n <ElementWithDropdown\n enabled={!readOnly && !disabled}\n isOpen={isOpen}\n renderElement={renderInputElement}\n renderDropdown={renderDropdown}\n onOpen={handleOpen}\n onClose={handleClose}\n onDismiss={handleDismiss}\n clickToToggle={false}\n offset={8}\n alignment={alignment}\n fitAvailableHeight\n customZIndex={dropdownZIndex}\n rootNode={dropdownRootNode}\n />\n </DropdownListState>\n );\n};\n"],"names":["PredictiveTextInput","_a","className","testId","selectedOption","minimumCharacters","fetchOptions","placeholder","readOnly","disabled","error","valueExtractor","listExtractor","displayValueExtractor","onSelectOption","alignment","dropdownZIndex","dropdownRootNode","dropdownWidth","ariaDescribedBy","otherProps","__rest","getDisplayValue","item","toString","input","setInput","useState","searchedInput","setSearchedInput","options","setOptions","isLoading","setIsLoading","isError","setIsError","isOptionSelected","setIsOptionSelected","prevOptionSelected","setPrevOptionSelected","isOpen","setIsOpen","isFocused","setIsFocused","internalId","useId","resultAnnouncement","setResultAnnouncement","instructionId","nodeRef","useRef","selectorRef","fetchOptionsRef","handleFetchOptions","useCallback","__awaiter","current","fetchedOptions","fetchOptionsDebounced","debounce","useEffect","length","cancel","undefined","handleDropdownDismiss","state","getItemsLoadState","count","handleListItemClick","extractedValue","focus","handleNodeFocus","handleNodeBlur","e","contains","relatedTarget","handleOnBlur","handleListDismiss","handleOnClear","prevValue","handleTyping","target","value","_jsx","DropdownListState","children","ElementWithDropdown","enabled","renderElement","_jsxs","InputWrapper","ref","tabIndex","onFocus","onBlur","$focused","$readOnly","$error","VisuallyHidden","id","Input","Object","assign","role","type","onChange","allowClear","onClear","styleType","concatIds","renderDropdown","_Fragment","DropdownList","listboxId","listItems","onSelectItem","onDismiss","itemsLoadState","itemTruncationType","itemMaxLines","labelDisplayType","disableItemFocus","onRetry","width","matchElementWidth","onOpen","onClose","clickToToggle","offset","fitAvailableHeight","customZIndex","rootNode"],"mappings":"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"}
1
+ {"version":3,"file":"predictive-text-input.js","sources":["../../src/predictive-text-input/predictive-text-input.tsx"],"sourcesContent":["import debounce from \"lodash/debounce\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { VisuallyHidden, concatIds } from \"src/shared/accessibility\";\nimport { Input } from \"../input\";\nimport { DropdownList, DropdownListState } from \"../shared/dropdown-list\";\nimport { ItemsLoadStateType } from \"../shared/dropdown-list/types\";\nimport { ElementWithDropdown } from \"../shared/dropdown-wrapper\";\nimport { InputWrapper } from \"../shared/input-wrapper/input-wrapper\";\nimport { useId } from \"../util\";\nimport { PredictiveTextInputProps } from \"./types\";\n\nexport const PredictiveTextInput = <T, V>({\n className,\n \"data-testid\": testId,\n selectedOption,\n minimumCharacters = 3,\n fetchOptions,\n placeholder = \"Enter here...\",\n readOnly = false,\n disabled = false,\n error,\n valueExtractor,\n listExtractor,\n displayValueExtractor,\n onSelectOption,\n alignment,\n dropdownZIndex,\n dropdownRootNode,\n dropdownWidth,\n \"aria-describedby\": ariaDescribedBy,\n ...otherProps\n}: PredictiveTextInputProps<T, V>): JSX.Element => {\n const getDisplayValue = (item: T | undefined): string => {\n if (!item) return \"\";\n return displayValueExtractor\n ? displayValueExtractor(item)\n : item.toString();\n };\n\n // =============================================================================\n // CONST, STATE\n // =============================================================================\n const [input, setInput] = useState<string>(() =>\n selectedOption ? getDisplayValue(selectedOption) : \"\"\n );\n const [searchedInput, setSearchedInput] = useState<string>(() =>\n selectedOption ? getDisplayValue(selectedOption) : \"\"\n );\n const [options, setOptions] = useState<T[]>([]);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [isError, setIsError] = useState<boolean>(false);\n const [isOptionSelected, setIsOptionSelected] = useState<boolean>(\n !!selectedOption\n );\n const [prevOptionSelected, setPrevOptionSelected] = useState<T | undefined>(\n selectedOption\n );\n const [isOpen, setIsOpen] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n const internalId = useId();\n const [resultAnnouncement, setResultAnnouncement] = useState<string | null>(\n null\n );\n const instructionId = `${internalId}-instruction`;\n\n const nodeRef = useRef<HTMLDivElement | null>(null);\n const selectorRef = useRef<HTMLInputElement | null>(null);\n\n const fetchOptionsRef = useRef(fetchOptions);\n\n // =============================================================================\n // DEBOUNCE FUNCTIONS\n // =============================================================================\n const handleFetchOptions = useCallback(async (input: string) => {\n if (!fetchOptionsRef.current) return;\n setIsError(false);\n setIsLoading(true);\n try {\n const fetchedOptions = await fetchOptionsRef.current(input);\n setSearchedInput(input);\n setOptions(fetchedOptions ?? []);\n setIsLoading(false);\n } catch {\n setIsError(true);\n setIsLoading(false);\n }\n }, []);\n\n const fetchOptionsDebounced = useCallback(\n debounce((input: string) => {\n handleFetchOptions(input);\n }, 500),\n [handleFetchOptions]\n );\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n\n useEffect(() => {\n fetchOptionsRef.current = fetchOptions;\n }, [fetchOptions]);\n\n useEffect(() => {\n /***\n * Should not fetch options for the following the scenario :\n * 1. When input < minimumCharacters\n * 2. When user selected option from dropdown becomes input\n * 3. Initial selectedOption passed in as input\n */\n if (input && input.length >= minimumCharacters) {\n if (!isOptionSelected) {\n setIsOpen(true);\n fetchOptionsDebounced(input);\n } else if (input !== searchedInput) {\n fetchOptionsDebounced(input);\n }\n } else {\n fetchOptionsDebounced.cancel();\n }\n\n if (input === \"\" && prevOptionSelected) {\n onSelectOption?.(undefined, undefined);\n handleDropdownDismiss();\n setPrevOptionSelected(undefined);\n }\n\n if (selectedOption && input !== getDisplayValue(selectedOption)) {\n setIsOptionSelected(false);\n }\n }, [input, selectedOption]);\n\n useEffect(() => {\n setInput(selectedOption ? getDisplayValue(selectedOption) : \"\");\n setSearchedInput(selectedOption ? getDisplayValue(selectedOption) : \"\");\n setPrevOptionSelected(selectedOption);\n setIsOptionSelected(!!selectedOption);\n }, [selectedOption]);\n\n useEffect(() => {\n const state = getItemsLoadState();\n const count = options?.length ?? 0;\n\n if (state === \"loading\" && input.length >= minimumCharacters) {\n setResultAnnouncement(\"Loading suggested results\");\n return;\n }\n\n if (state === \"fail\") {\n setResultAnnouncement(\"Suggestions failed to load. Try again.\");\n return;\n }\n\n if (isOpen && !isLoading && !isError) {\n if (count === 0) {\n setResultAnnouncement(input ? \"No results found.\" : null);\n } else {\n setResultAnnouncement(\n `${count} result${\n count > 1 ? \"s\" : \"\"\n } found. Press down arrow to scroll through the list.`\n );\n }\n }\n }, [options, input, isError, isLoading]);\n\n // =============================================================================\n // Cleanup: cancel debounce on unmount\n // =============================================================================\n useEffect(() => {\n return () => {\n fetchOptionsDebounced.cancel();\n };\n }, [fetchOptionsDebounced]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleListItemClick = (item: T, extractedValue: V) => {\n selectorRef.current?.focus();\n setInput(getDisplayValue(item));\n setSearchedInput(item ? getDisplayValue(item) : \"\");\n setIsOptionSelected(true);\n setPrevOptionSelected(item);\n setIsOpen(false);\n onSelectOption?.(item, extractedValue);\n };\n\n const handleOpen = () => {\n if (!isOptionSelected && input.length >= minimumCharacters) {\n setIsFocused(true);\n }\n };\n\n const handleClose = () => {\n setIsOpen(false);\n setIsFocused(false);\n handleOnBlur();\n };\n\n const handleNodeFocus = () => {\n setIsFocused(true);\n };\n\n const handleNodeBlur = (e: React.FocusEvent) => {\n if (\n !isOpen &&\n nodeRef.current &&\n !nodeRef.current.contains(e.relatedTarget as Node)\n ) {\n setIsFocused(false);\n handleOnBlur();\n }\n };\n\n const handleListDismiss = () => {\n setIsOpen(false);\n setIsFocused(false);\n };\n\n const handleDismiss = () => {\n setIsOpen(false);\n setIsFocused(false);\n handleOnBlur();\n selectorRef.current?.focus();\n };\n\n const handleHide = () => {\n // reset dropdown state once it fully closes\n setOptions([]);\n setIsLoading(true);\n setIsError(false);\n };\n\n const handleOnClear = () => {\n setInput(\"\");\n setIsOptionSelected(false);\n setIsOpen(false);\n onSelectOption?.(undefined, undefined);\n };\n\n const handleOnBlur = () => {\n if (!isOptionSelected) {\n if (prevOptionSelected) {\n const prevValue = getDisplayValue(prevOptionSelected);\n setInput(prevValue);\n setIsOpen(false);\n } else {\n handleOnClear();\n }\n }\n };\n\n const handleTyping = (e: React.ChangeEvent<HTMLInputElement>) => {\n setInput(e.target.value);\n setIsOptionSelected(false);\n };\n\n const handleDropdownDismiss = (item?: T) => {\n setSearchedInput(item ? getDisplayValue(item) : \"\");\n setIsOptionSelected(!!item);\n setIsLoading(true);\n };\n\n // =============================================================================\n // HELPER FUNCTION\n // =============================================================================\n const getItemsLoadState = (): ItemsLoadStateType => {\n if (isError) return \"fail\";\n return isLoading ? \"loading\" : \"success\";\n };\n\n // =============================================================================\n // RENDER FUNCTION\n // =============================================================================\n const renderInputElement = () => {\n return (\n <InputWrapper\n className={className}\n data-testid={testId}\n ref={nodeRef}\n tabIndex={-1}\n onFocus={handleNodeFocus}\n onBlur={handleNodeBlur}\n $focused={isFocused}\n $disabled={disabled}\n $readOnly={readOnly}\n $error={error}\n >\n <VisuallyHidden id={instructionId} aria-hidden>\n Type in {minimumCharacters} or more characters for suggested\n results.\n </VisuallyHidden>\n {resultAnnouncement && (\n <VisuallyHidden aria-live=\"polite\">\n {resultAnnouncement}\n </VisuallyHidden>\n )}\n <Input\n role=\"combobox\"\n ref={selectorRef}\n id={internalId}\n type=\"text\"\n value={input}\n onChange={handleTyping}\n placeholder={placeholder}\n readOnly={readOnly}\n disabled={disabled}\n allowClear\n onClear={handleOnClear}\n aria-expanded={isOpen}\n aria-controls={internalId}\n aria-autocomplete=\"list\"\n aria-haspopup=\"listbox\"\n onBlur={\n input.length < minimumCharacters\n ? handleOnBlur\n : undefined\n }\n styleType=\"no-border\"\n aria-describedby={concatIds(ariaDescribedBy, instructionId)}\n {...otherProps}\n />\n </InputWrapper>\n );\n };\n\n const renderDropdown = () => {\n return (\n <DropdownList\n listboxId={internalId}\n listItems={options}\n onSelectItem={handleListItemClick}\n onDismiss={handleListDismiss}\n valueExtractor={valueExtractor}\n listExtractor={listExtractor}\n itemsLoadState={getItemsLoadState()}\n itemTruncationType={\"end\"}\n itemMaxLines={1}\n labelDisplayType={\"next-line\"}\n disableItemFocus\n onRetry={() => handleFetchOptions(input)}\n width={dropdownWidth}\n matchElementWidth\n />\n );\n };\n\n return (\n <DropdownListState>\n <ElementWithDropdown\n enabled={!readOnly && !disabled}\n isOpen={isOpen}\n renderElement={renderInputElement}\n renderDropdown={renderDropdown}\n onOpen={handleOpen}\n onClose={handleClose}\n onDismiss={handleDismiss}\n onHide={handleHide}\n clickToToggle={false}\n offset={8}\n alignment={alignment}\n fitAvailableHeight\n customZIndex={dropdownZIndex}\n rootNode={dropdownRootNode}\n />\n </DropdownListState>\n );\n};\n"],"names":["PredictiveTextInput","_a","className","testId","selectedOption","minimumCharacters","fetchOptions","placeholder","readOnly","disabled","error","valueExtractor","listExtractor","displayValueExtractor","onSelectOption","alignment","dropdownZIndex","dropdownRootNode","dropdownWidth","ariaDescribedBy","otherProps","__rest","getDisplayValue","item","toString","input","setInput","useState","searchedInput","setSearchedInput","options","setOptions","isLoading","setIsLoading","isError","setIsError","isOptionSelected","setIsOptionSelected","prevOptionSelected","setPrevOptionSelected","isOpen","setIsOpen","isFocused","setIsFocused","internalId","useId","resultAnnouncement","setResultAnnouncement","instructionId","nodeRef","useRef","selectorRef","fetchOptionsRef","handleFetchOptions","useCallback","__awaiter","current","fetchedOptions","fetchOptionsDebounced","debounce","useEffect","length","cancel","undefined","handleDropdownDismiss","state","getItemsLoadState","count","handleListItemClick","extractedValue","focus","handleNodeFocus","handleNodeBlur","e","contains","relatedTarget","handleOnBlur","handleListDismiss","handleOnClear","prevValue","handleTyping","target","value","_jsx","DropdownListState","children","ElementWithDropdown","enabled","renderElement","_jsxs","InputWrapper","ref","tabIndex","onFocus","onBlur","$focused","$readOnly","$error","VisuallyHidden","id","Input","Object","assign","role","type","onChange","allowClear","onClear","styleType","concatIds","renderDropdown","DropdownList","listboxId","listItems","onSelectItem","onDismiss","itemsLoadState","itemTruncationType","itemMaxLines","labelDisplayType","disableItemFocus","onRetry","width","matchElementWidth","onOpen","onClose","onHide","clickToToggle","offset","fitAvailableHeight","customZIndex","rootNode"],"mappings":"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"}
@@ -10,9 +10,10 @@ export interface DropdownRenderProps {
10
10
  interface ElementWithDropdownProps {
11
11
  enabled: boolean;
12
12
  isOpen: boolean;
13
- onOpen?: () => void | undefined;
14
- onClose?: (reason: OpenChangeReason | undefined) => void | undefined;
15
- onDismiss?: () => void | undefined;
13
+ onOpen?: (() => void) | undefined;
14
+ onClose?: ((reason: OpenChangeReason | undefined) => void) | undefined;
15
+ onDismiss?: (() => void) | undefined;
16
+ onHide?: (() => void) | undefined;
16
17
  renderElement: () => React.ReactNode;
17
18
  renderDropdown: (props: DropdownRenderProps) => React.ReactNode;
18
19
  customZIndex?: number | undefined;
@@ -62,5 +63,5 @@ export declare const useDropdownRender: () => DropdownRenderProps;
62
63
  * })
63
64
  * ```
64
65
  */
65
- export declare const ElementWithDropdown: ({ enabled, isOpen, onOpen, onClose, onDismiss, renderElement, renderDropdown, customZIndex, clickToToggle, offset: dropdownOffset, alignment, fitAvailableHeight, rootNode, positionRef, }: ElementWithDropdownProps) => import("react/jsx-runtime").JSX.Element;
66
+ export declare const ElementWithDropdown: ({ enabled, isOpen, onOpen, onClose, onDismiss, onHide, renderElement, renderDropdown, customZIndex, clickToToggle, offset: dropdownOffset, alignment, fitAvailableHeight, rootNode, positionRef, }: ElementWithDropdownProps) => import("react/jsx-runtime").JSX.Element;
66
67
  export {};
@@ -1,2 +1,2 @@
1
- import{jsxs as e,Fragment as t,jsx as n}from"react/jsx-runtime";import{useFloating as i,autoUpdate as o,offset as l,flip as r,shift as a,limitShift as s,size as d,useTransitionStyles as m,useClick as c,useDismiss as g,useInteractions as p,FloatingPortal as f,FloatingFocusManager as h}from"@floating-ui/react";import{createContext as u,useContext as b,useRef as x}from"react";import{useResizeDetector as y}from"../../external/react-resize-detector/build/index.esm.js";import{ThemeContext as w}from"styled-components";import{useFloatingChild as v}from"../../overlay/use-floating-context.js";import{Breakpoint as j}from"../../theme/index.js";const F=e=>"right"===e?"bottom-end":"bottom-start",O=u({elementWidth:0,styles:{},setFloatingRef:()=>{},getFloatingProps:()=>({})}),P=()=>b(O),R=({enabled:u,isOpen:P,onOpen:R,onClose:H,onDismiss:W,renderElement:k,renderDropdown:M,customZIndex:z,clickToToggle:C=!1,offset:D=0,alignment:E="left",fitAvailableHeight:I,rootNode:T,positionRef:A})=>{var N;const S=b(w),Z=j["sm-max"]({theme:S}),$=x(null),{width:q=0}=y({targetRef:null!=A?A:$,handleHeight:!1}),B={name:"center",fn:({x:e,rects:t})=>{const n=0===e||e+t.floating.width===window.innerWidth,i=window.innerWidth<Z;return{x:n&&i?(window.innerWidth-t.floating.width)/2:e}}},{refs:G,floatingStyles:J,context:K}=i({open:P,onOpenChange:(e,t,n)=>{"escape-key"===n?null==W||W():e&&!P?null==R||R():!e&&P&&(null==H||H(n))},whileElementsMounted:o,placement:F(E),middleware:[l(D),r(),a({limiter:s()}),d({apply({availableHeight:e,elements:t}){!I||e>=t.floating.scrollHeight?t.floating.style.setProperty("--available-height",""):t.floating.style.setProperty("--available-height",`${Math.max(0,e)}px`)}}),B]}),L=v(),{isMounted:Q,styles:U}=m(K,{initial:{opacity:0},open:{opacity:1},duration:300}),V=c(K,{enabled:u,toggle:C,keyboardHandlers:C}),X=g(K,{enabled:u}),{getReferenceProps:Y,getFloatingProps:_}=p([V,X]),ee={elementWidth:q,styles:Object.assign(Object.assign(Object.assign({},U),J),{zIndex:null!==(N=null!=z?z:L)&&void 0!==N?N:50}),setFloatingRef:G.setFloating,getFloatingProps:_};return e(t,{children:[n("div",Object.assign({ref:e=>{$.current=e,G.setReference(e)}},Y(),{children:k()})),Q&&n(f,{root:T,children:n(h,{context:K,modal:!1,initialFocus:-1,returnFocus:!1,children:n(O.Provider,{value:ee,children:M(ee)})})})]})};export{O as DropdownRenderContext,R as ElementWithDropdown,P as useDropdownRender};
1
+ import{jsxs as e,Fragment as t,jsx as i}from"react/jsx-runtime";import{useFloating as n,autoUpdate as o,offset as r,flip as l,shift as s,limitShift as a,size as d,useTransitionStyles as m,useClick as p,useDismiss as c,useInteractions as g,FloatingPortal as u,FloatingFocusManager as h}from"@floating-ui/react";import{createContext as f,useContext as b,useRef as j,useEffect as x}from"react";import{useResizeDetector as y}from"../../external/react-resize-detector/build/index.esm.js";import{ThemeContext as v}from"styled-components";import{useFloatingChild as w}from"../../overlay/use-floating-context.js";import{Breakpoint as F}from"../../theme/index.js";import"../../util/calendar-helper.js";import"../../util/date-helper.js";import"../../util/date-input-helper.js";import"../../util/simple-id-generator.js";import"../../util/string-helper.js";import"@react-aria/live-announcer";import{useEvent as O}from"../../util/use-event.js";import{usePrevious as P}from"../../util/use-previous.js";const H=e=>"right"===e?"bottom-end":"bottom-start",R=f({elementWidth:0,styles:{},setFloatingRef:()=>{},getFloatingProps:()=>({})}),W=()=>b(R),k=({enabled:f,isOpen:W,onOpen:k,onClose:M,onDismiss:z,onHide:C,renderElement:D,renderDropdown:E,customZIndex:I,clickToToggle:T=!1,offset:A=0,alignment:N="left",fitAvailableHeight:S,rootNode:Z,positionRef:$})=>{var q;const B=b(v),G=F["sm-max"]({theme:B}),J=j(null),{width:K=0}=y({targetRef:null!=$?$:J,handleHeight:!1}),L={name:"center",fn:({x:e,rects:t})=>{const i=0===e||e+t.floating.width===window.innerWidth,n=window.innerWidth<G;return{x:i&&n?(window.innerWidth-t.floating.width)/2:e}}},{refs:Q,floatingStyles:U,context:V}=n({open:W,onOpenChange:(e,t,i)=>{"escape-key"===i?null==z||z():e&&!W?null==k||k():!e&&W&&(null==M||M(i))},whileElementsMounted:o,placement:H(N),middleware:[r(A),l(),s({limiter:a()}),d({apply({availableHeight:e,elements:t}){!S||e>=t.floating.scrollHeight?t.floating.style.setProperty("--available-height",""):t.floating.style.setProperty("--available-height",`${Math.max(0,e)}px`)}}),L]}),X=w(),{isMounted:Y,styles:_}=m(V,{initial:{opacity:0},open:{opacity:1},duration:300}),ee=p(V,{enabled:f,toggle:T,keyboardHandlers:T}),te=c(V,{enabled:f}),{getReferenceProps:ie,getFloatingProps:ne}=g([ee,te]),oe=P(Y),re=O((()=>null==C?void 0:C()));x((()=>{oe&&!Y&&re()}),[oe,Y,re]);const le={elementWidth:K,styles:Object.assign(Object.assign(Object.assign({},_),U),{zIndex:null!==(q=null!=I?I:X)&&void 0!==q?q:50}),setFloatingRef:Q.setFloating,getFloatingProps:ne};return e(t,{children:[i("div",Object.assign({ref:e=>{J.current=e,Q.setReference(e)}},ie(),{children:D()})),Y&&i(u,{root:Z,children:i(h,{context:V,modal:!1,initialFocus:-1,returnFocus:!1,children:i(R.Provider,{value:le,children:E(le)})})})]})};export{R as DropdownRenderContext,k as ElementWithDropdown,W as useDropdownRender};
2
2
  //# sourceMappingURL=element-with-dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"element-with-dropdown.js","sources":["../../../src/shared/dropdown-wrapper/element-with-dropdown.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n Middleware,\n OpenChangeReason,\n Placement,\n autoUpdate,\n flip,\n limitShift,\n offset,\n shift,\n size,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport {\n CSSProperties,\n RefObject,\n createContext,\n useContext,\n useRef,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport { ThemeContext } from \"styled-components\";\nimport { useFloatingChild } from \"../../overlay/use-floating-context\";\nimport { Breakpoint } from \"../../theme\";\nimport { DropdownAlignmentType } from \"./types\";\n\nexport interface DropdownRenderProps {\n elementWidth: number;\n styles: CSSProperties;\n setFloatingRef: (node: HTMLElement | null) => void;\n getFloatingProps: (\n userProps?: React.HTMLProps<HTMLElement>\n ) => Record<string, unknown>;\n}\n\ninterface ElementWithDropdownProps {\n enabled: boolean;\n isOpen: boolean;\n onOpen?: () => void | undefined;\n onClose?: (reason: OpenChangeReason | undefined) => void | undefined;\n onDismiss?: () => void | undefined;\n renderElement: () => React.ReactNode;\n renderDropdown: (props: DropdownRenderProps) => React.ReactNode;\n customZIndex?: number | undefined;\n clickToToggle?: boolean | undefined;\n /* the distance between the reference element and the dropdown */\n offset?: number | undefined;\n /* the alignment of the dropdown to the left or right of the reference element */\n alignment?: DropdownAlignmentType | undefined;\n fitAvailableHeight?: boolean | undefined;\n /**\n * The root element that contains the popover element. Defaults to the document body.\n *\n * If the parent that contains the trigger element has a higher z-index than the popover,\n * the popover may not be visible. Specify the parent element here instead\n */\n rootNode?: RefObject<HTMLElement> | undefined;\n /** If set, the `elementWidth` refers to this instead of the reference element */\n positionRef?: RefObject<HTMLElement> | undefined;\n}\n\nconst getFloatingPlacement = (alignment: DropdownAlignmentType): Placement => {\n switch (alignment) {\n case \"right\":\n return \"bottom-end\";\n case \"left\":\n default:\n return \"bottom-start\";\n }\n};\n\nconst DEFAULT_Z_INDEX = 50;\n\nexport const DropdownRenderContext = createContext<DropdownRenderProps>({\n elementWidth: 0,\n styles: {},\n setFloatingRef: () => {\n // noop\n },\n getFloatingProps: () => ({}),\n});\n\nexport const useDropdownRender = () => {\n return useContext(DropdownRenderContext);\n};\n\n/**\n * A wrapper to handle the common pattern of a field with a card-based dropdown\n * using Floating UI\n *\n * Usage:\n * - Specify `renderElement` for the main field\n * - Specify `renderDropdown` for the dropdown\n * - Use `isOpen` to control the visibility of the dropdown\n * - Handle changes in visibility with `onOpen`, `onClose` and `onDismiss`\n * - If your dropdown can resize, set the css like so: `max-height: var(--available-height);`\n * - If your dropdown has a preferred max-height, set the css like so:\n * `max-height: min(100px, var(--available-height, infinity * 1px))`\n *\n * Pass the floating props to the dropdown:\n * ```\n * <DropdownContainer\n * ref={setFloatingRef}\n * style={styles}\n * {...getFloatingProps()}\n * >\n * </DropdownContainer>\n * ```\n *\n * If you need event listeners, pass them to `getFloatingProps()`:\n * ```\n * getFloatingProps({\n * onClick: handleOnClick\n * })\n * ```\n */\nexport const ElementWithDropdown = ({\n enabled,\n isOpen,\n onOpen,\n onClose,\n onDismiss,\n renderElement,\n renderDropdown,\n customZIndex,\n clickToToggle = false,\n offset: dropdownOffset = 0,\n alignment = \"left\",\n fitAvailableHeight,\n rootNode,\n positionRef,\n}: ElementWithDropdownProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const theme = useContext(ThemeContext);\n const mobileBreakpoint = Breakpoint[\"sm-max\"]({ theme });\n const elementRef = useRef<HTMLDivElement | null>(null);\n const { width: referenceWidth = 0 } = useResizeDetector({\n targetRef: positionRef ?? elementRef,\n handleHeight: false,\n });\n const center: Middleware = {\n name: \"center\",\n fn: ({ x, rects }) => {\n const noGapInBetween =\n x === 0 || x + rects.floating.width === window.innerWidth;\n const isMobileScreen = window.innerWidth < mobileBreakpoint;\n return {\n x:\n noGapInBetween && isMobileScreen\n ? (window.innerWidth - rects.floating.width) / 2\n : x,\n };\n },\n };\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: (open, _event, reason) => {\n if (reason === \"escape-key\") {\n onDismiss?.();\n } else if (open && !isOpen) {\n onOpen?.();\n } else if (!open && isOpen) {\n onClose?.(reason);\n }\n },\n whileElementsMounted: autoUpdate,\n placement: getFloatingPlacement(alignment),\n middleware: [\n offset(dropdownOffset),\n flip(),\n shift({\n limiter: limitShift(),\n }),\n size({\n // shrink to fit available vertical space\n apply({ availableHeight, elements }) {\n if (\n !fitAvailableHeight ||\n availableHeight >= elements.floating.scrollHeight\n ) {\n // reset this so that dropdown can expand as needed\n elements.floating.style.setProperty(\n \"--available-height\",\n \"\"\n );\n return;\n }\n\n elements.floating.style.setProperty(\n \"--available-height\",\n `${Math.max(0, availableHeight)}px`\n );\n },\n }),\n center,\n ],\n });\n const parentZIndex = useFloatingChild();\n\n const { isMounted, styles } = useTransitionStyles(context, {\n initial: { opacity: 0 },\n open: { opacity: 1 },\n duration: 300,\n });\n\n const click = useClick(context, {\n enabled,\n toggle: clickToToggle,\n keyboardHandlers: clickToToggle,\n });\n const dismiss = useDismiss(context, { enabled });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n click,\n dismiss,\n ]);\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const dropdownRenderProps = {\n elementWidth: referenceWidth,\n styles: {\n ...styles,\n ...floatingStyles,\n zIndex: customZIndex ?? parentZIndex ?? DEFAULT_Z_INDEX,\n },\n setFloatingRef: refs.setFloating,\n getFloatingProps,\n };\n\n return (\n <>\n <div\n ref={(node) => {\n elementRef.current = node;\n refs.setReference(node);\n }}\n {...getReferenceProps()}\n >\n {renderElement()}\n </div>\n {isMounted && (\n <FloatingPortal root={rootNode}>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={-1}\n returnFocus={false} // leads to focus trap. parent to handle the final focus state\n >\n <DropdownRenderContext.Provider\n value={dropdownRenderProps}\n >\n {renderDropdown(dropdownRenderProps)}\n </DropdownRenderContext.Provider>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </>\n );\n};\n"],"names":["getFloatingPlacement","alignment","DropdownRenderContext","createContext","elementWidth","styles","setFloatingRef","getFloatingProps","useDropdownRender","useContext","ElementWithDropdown","enabled","isOpen","onOpen","onClose","onDismiss","renderElement","renderDropdown","customZIndex","clickToToggle","offset","dropdownOffset","fitAvailableHeight","rootNode","positionRef","theme","ThemeContext","mobileBreakpoint","Breakpoint","elementRef","useRef","width","referenceWidth","useResizeDetector","targetRef","handleHeight","center","name","fn","x","rects","noGapInBetween","floating","window","innerWidth","isMobileScreen","refs","floatingStyles","context","useFloating","open","onOpenChange","_event","reason","whileElementsMounted","autoUpdate","placement","middleware","flip","shift","limiter","limitShift","size","apply","availableHeight","elements","scrollHeight","style","setProperty","Math","max","parentZIndex","useFloatingChild","isMounted","useTransitionStyles","initial","opacity","duration","click","useClick","toggle","keyboardHandlers","dismiss","useDismiss","getReferenceProps","useInteractions","dropdownRenderProps","zIndex","_a","setFloating","_jsxs","_jsx","Object","assign","ref","node","current","setReference","children","FloatingPortal","root","FloatingFocusManager","modal","initialFocus","returnFocus","Provider","value"],"mappings":"goBAkEA,MAAMA,EAAwBC,GAEjB,UADDA,EAEO,aAGA,eAMNC,EAAwBC,EAAmC,CACpEC,aAAc,EACdC,OAAQ,CAAA,EACRC,eAAgB,OAGhBC,iBAAkB,KAAA,CAAS,KAGlBC,EAAoB,IACtBC,EAAWP,GAiCTQ,EAAsB,EAC/BC,UACAC,SACAC,SACAC,UACAC,YACAC,gBACAC,iBACAC,eACAC,iBAAgB,EAChBC,OAAQC,EAAiB,EACzBpB,YAAY,OACZqB,qBACAC,WACAC,wBAKA,MAAMC,EAAQhB,EAAWiB,GACnBC,EAAmBC,EAAW,UAAU,CAAEH,UAC1CI,EAAaC,EAA8B,OACzCC,MAAOC,EAAiB,GAAMC,EAAkB,CACpDC,UAAWV,QAAAA,EAAeK,EAC1BM,cAAc,IAEZC,EAAqB,CACvBC,KAAM,SACNC,GAAI,EAAGC,IAAGC,YACN,MAAMC,EACI,IAANF,GAAWA,EAAIC,EAAME,SAASX,QAAUY,OAAOC,WAC7CC,EAAiBF,OAAOC,WAAajB,EAC3C,MAAO,CACHY,EACIE,GAAkBI,GACXF,OAAOC,WAAaJ,EAAME,SAASX,OAAS,EAC7CQ,EACb,IAGHO,KAAEA,EAAIC,eAAEA,EAAcC,QAAEA,GAAYC,EAAY,CAClDC,KAAMtC,EACNuC,aAAc,CAACD,EAAME,EAAQC,KACV,eAAXA,EACAtC,SAAAA,IACOmC,IAAStC,EAChBC,SAAAA,KACQqC,GAAQtC,IAChBE,SAAAA,EAAUuC,GACd,EAEJC,qBAAsBC,EACtBC,UAAWxD,EAAqBC,GAChCwD,WAAY,CACRrC,EAAOC,GACPqC,IACAC,EAAM,CACFC,QAASC,MAEbC,EAAK,CAED,KAAAC,EAAMC,gBAAEA,EAAeC,SAAEA,KAEhB3C,GACD0C,GAAmBC,EAASvB,SAASwB,aAGrCD,EAASvB,SAASyB,MAAMC,YACpB,qBACA,IAKRH,EAASvB,SAASyB,MAAMC,YACpB,qBACA,GAAGC,KAAKC,IAAI,EAAGN,OAEvB,IAEJ5B,KAGFmC,EAAeC,KAEfC,UAAEA,EAASpE,OAAEA,GAAWqE,EAAoB1B,EAAS,CACvD2B,QAAS,CAAEC,QAAS,GACpB1B,KAAM,CAAE0B,QAAS,GACjBC,SAAU,MAGRC,EAAQC,EAAS/B,EAAS,CAC5BrC,UACAqE,OAAQ7D,EACR8D,iBAAkB9D,IAEhB+D,EAAUC,EAAWnC,EAAS,CAAErC,aAEhCyE,kBAAEA,EAAiB7E,iBAAEA,GAAqB8E,EAAgB,CAC5DP,EACAI,IAMEI,GAAsB,CACxBlF,aAAc4B,EACd3B,oDACOA,GACA0C,GAAc,CACjBwC,OAAoC,QAA5BC,EAAAtE,QAAAA,EAAgBqD,SAAY,IAAAiB,EAAAA,EA5JxB,KA8JhBlF,eAAgBwC,EAAK2C,YACrBlF,oBAGJ,OACImF,eACIC,EAAA,MAAAC,OAAAC,OAAA,CACIC,IAAMC,IACFlE,EAAWmE,QAAUD,EACrBjD,EAAKmD,aAAaF,EAAK,GAEvBX,IAAmB,CAAAc,SAEtBlF,OAEJyD,GACGkB,EAACQ,GAAeC,KAAM7E,EAAQ2E,SAC1BP,EAACU,EAAoB,CACjBrD,QAASA,EACTsD,OAAO,EACPC,cAAc,EACdC,aAAa,EAAKN,SAElBP,EAACzF,EAAsBuG,SAAQ,CAC3BC,MAAOpB,GAAmBY,SAEzBjF,EAAeqE,YAKjC"}
1
+ {"version":3,"file":"element-with-dropdown.js","sources":["../../../src/shared/dropdown-wrapper/element-with-dropdown.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n Middleware,\n OpenChangeReason,\n Placement,\n autoUpdate,\n flip,\n limitShift,\n offset,\n shift,\n size,\n useClick,\n useDismiss,\n useFloating,\n useInteractions,\n useTransitionStyles,\n} from \"@floating-ui/react\";\nimport {\n CSSProperties,\n RefObject,\n createContext,\n useContext,\n useEffect,\n useRef,\n} from \"react\";\nimport { useResizeDetector } from \"react-resize-detector\";\nimport { ThemeContext } from \"styled-components\";\nimport { useFloatingChild } from \"../../overlay/use-floating-context\";\nimport { Breakpoint } from \"../../theme\";\nimport { useEvent, usePrevious } from \"../../util\";\nimport { DropdownAlignmentType } from \"./types\";\n\nexport interface DropdownRenderProps {\n elementWidth: number;\n styles: CSSProperties;\n setFloatingRef: (node: HTMLElement | null) => void;\n getFloatingProps: (\n userProps?: React.HTMLProps<HTMLElement>\n ) => Record<string, unknown>;\n}\n\ninterface ElementWithDropdownProps {\n enabled: boolean;\n isOpen: boolean;\n onOpen?: (() => void) | undefined;\n onClose?: ((reason: OpenChangeReason | undefined) => void) | undefined;\n onDismiss?: (() => void) | undefined;\n onHide?: (() => void) | undefined;\n renderElement: () => React.ReactNode;\n renderDropdown: (props: DropdownRenderProps) => React.ReactNode;\n customZIndex?: number | undefined;\n clickToToggle?: boolean | undefined;\n /* the distance between the reference element and the dropdown */\n offset?: number | undefined;\n /* the alignment of the dropdown to the left or right of the reference element */\n alignment?: DropdownAlignmentType | undefined;\n fitAvailableHeight?: boolean | undefined;\n /**\n * The root element that contains the popover element. Defaults to the document body.\n *\n * If the parent that contains the trigger element has a higher z-index than the popover,\n * the popover may not be visible. Specify the parent element here instead\n */\n rootNode?: RefObject<HTMLElement> | undefined;\n /** If set, the `elementWidth` refers to this instead of the reference element */\n positionRef?: RefObject<HTMLElement> | undefined;\n}\n\nconst getFloatingPlacement = (alignment: DropdownAlignmentType): Placement => {\n switch (alignment) {\n case \"right\":\n return \"bottom-end\";\n case \"left\":\n default:\n return \"bottom-start\";\n }\n};\n\nconst DEFAULT_Z_INDEX = 50;\n\nexport const DropdownRenderContext = createContext<DropdownRenderProps>({\n elementWidth: 0,\n styles: {},\n setFloatingRef: () => {\n // noop\n },\n getFloatingProps: () => ({}),\n});\n\nexport const useDropdownRender = () => {\n return useContext(DropdownRenderContext);\n};\n\n/**\n * A wrapper to handle the common pattern of a field with a card-based dropdown\n * using Floating UI\n *\n * Usage:\n * - Specify `renderElement` for the main field\n * - Specify `renderDropdown` for the dropdown\n * - Use `isOpen` to control the visibility of the dropdown\n * - Handle changes in visibility with `onOpen`, `onClose` and `onDismiss`\n * - If your dropdown can resize, set the css like so: `max-height: var(--available-height);`\n * - If your dropdown has a preferred max-height, set the css like so:\n * `max-height: min(100px, var(--available-height, infinity * 1px))`\n *\n * Pass the floating props to the dropdown:\n * ```\n * <DropdownContainer\n * ref={setFloatingRef}\n * style={styles}\n * {...getFloatingProps()}\n * >\n * </DropdownContainer>\n * ```\n *\n * If you need event listeners, pass them to `getFloatingProps()`:\n * ```\n * getFloatingProps({\n * onClick: handleOnClick\n * })\n * ```\n */\nexport const ElementWithDropdown = ({\n enabled,\n isOpen,\n onOpen,\n onClose,\n onDismiss,\n onHide,\n renderElement,\n renderDropdown,\n customZIndex,\n clickToToggle = false,\n offset: dropdownOffset = 0,\n alignment = \"left\",\n fitAvailableHeight,\n rootNode,\n positionRef,\n}: ElementWithDropdownProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const theme = useContext(ThemeContext);\n const mobileBreakpoint = Breakpoint[\"sm-max\"]({ theme });\n const elementRef = useRef<HTMLDivElement | null>(null);\n const { width: referenceWidth = 0 } = useResizeDetector({\n targetRef: positionRef ?? elementRef,\n handleHeight: false,\n });\n const center: Middleware = {\n name: \"center\",\n fn: ({ x, rects }) => {\n const noGapInBetween =\n x === 0 || x + rects.floating.width === window.innerWidth;\n const isMobileScreen = window.innerWidth < mobileBreakpoint;\n return {\n x:\n noGapInBetween && isMobileScreen\n ? (window.innerWidth - rects.floating.width) / 2\n : x,\n };\n },\n };\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: (open, _event, reason) => {\n if (reason === \"escape-key\") {\n onDismiss?.();\n } else if (open && !isOpen) {\n onOpen?.();\n } else if (!open && isOpen) {\n onClose?.(reason);\n }\n },\n whileElementsMounted: autoUpdate,\n placement: getFloatingPlacement(alignment),\n middleware: [\n offset(dropdownOffset),\n flip(),\n shift({\n limiter: limitShift(),\n }),\n size({\n // shrink to fit available vertical space\n apply({ availableHeight, elements }) {\n if (\n !fitAvailableHeight ||\n availableHeight >= elements.floating.scrollHeight\n ) {\n // reset this so that dropdown can expand as needed\n elements.floating.style.setProperty(\n \"--available-height\",\n \"\"\n );\n return;\n }\n\n elements.floating.style.setProperty(\n \"--available-height\",\n `${Math.max(0, availableHeight)}px`\n );\n },\n }),\n center,\n ],\n });\n const parentZIndex = useFloatingChild();\n\n const { isMounted, styles } = useTransitionStyles(context, {\n initial: { opacity: 0 },\n open: { opacity: 1 },\n duration: 300,\n });\n\n const click = useClick(context, {\n enabled,\n toggle: clickToToggle,\n keyboardHandlers: clickToToggle,\n });\n const dismiss = useDismiss(context, { enabled });\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n click,\n dismiss,\n ]);\n\n // =========================================================================\n // ON HIDE EFFECT\n // =========================================================================\n const prevIsMounted = usePrevious(isMounted);\n const onHideEvent = useEvent(() => onHide?.());\n\n useEffect(() => {\n if (prevIsMounted && !isMounted) {\n onHideEvent();\n }\n }, [prevIsMounted, isMounted, onHideEvent]);\n\n // =========================================================================\n // RENDER FUNCTIONS\n // =========================================================================\n const dropdownRenderProps = {\n elementWidth: referenceWidth,\n styles: {\n ...styles,\n ...floatingStyles,\n zIndex: customZIndex ?? parentZIndex ?? DEFAULT_Z_INDEX,\n },\n setFloatingRef: refs.setFloating,\n getFloatingProps,\n };\n\n return (\n <>\n <div\n ref={(node) => {\n elementRef.current = node;\n refs.setReference(node);\n }}\n {...getReferenceProps()}\n >\n {renderElement()}\n </div>\n {isMounted && (\n <FloatingPortal root={rootNode}>\n <FloatingFocusManager\n context={context}\n modal={false}\n initialFocus={-1}\n returnFocus={false} // leads to focus trap. parent to handle the final focus state\n >\n <DropdownRenderContext.Provider\n value={dropdownRenderProps}\n >\n {renderDropdown(dropdownRenderProps)}\n </DropdownRenderContext.Provider>\n </FloatingFocusManager>\n </FloatingPortal>\n )}\n </>\n );\n};\n"],"names":["getFloatingPlacement","alignment","DropdownRenderContext","createContext","elementWidth","styles","setFloatingRef","getFloatingProps","useDropdownRender","useContext","ElementWithDropdown","enabled","isOpen","onOpen","onClose","onDismiss","onHide","renderElement","renderDropdown","customZIndex","clickToToggle","offset","dropdownOffset","fitAvailableHeight","rootNode","positionRef","theme","ThemeContext","mobileBreakpoint","Breakpoint","elementRef","useRef","width","referenceWidth","useResizeDetector","targetRef","handleHeight","center","name","fn","x","rects","noGapInBetween","floating","window","innerWidth","isMobileScreen","refs","floatingStyles","context","useFloating","open","onOpenChange","_event","reason","whileElementsMounted","autoUpdate","placement","middleware","flip","shift","limiter","limitShift","size","apply","availableHeight","elements","scrollHeight","style","setProperty","Math","max","parentZIndex","useFloatingChild","isMounted","useTransitionStyles","initial","opacity","duration","click","useClick","toggle","keyboardHandlers","dismiss","useDismiss","getReferenceProps","useInteractions","prevIsMounted","usePrevious","onHideEvent","useEvent","useEffect","dropdownRenderProps","zIndex","_a","setFloating","_jsxs","_jsx","Object","assign","ref","node","current","setReference","children","FloatingPortal","root","FloatingFocusManager","modal","initialFocus","returnFocus","Provider","value"],"mappings":"49BAqEA,MAAMA,EAAwBC,GAEjB,UADDA,EAEO,aAGA,eAMNC,EAAwBC,EAAmC,CACpEC,aAAc,EACdC,OAAQ,CAAA,EACRC,eAAgB,OAGhBC,iBAAkB,KAAA,CAAS,KAGlBC,EAAoB,IACtBC,EAAWP,GAiCTQ,EAAsB,EAC/BC,UACAC,SACAC,SACAC,UACAC,YACAC,SACAC,gBACAC,iBACAC,eACAC,iBAAgB,EAChBC,OAAQC,EAAiB,EACzBrB,YAAY,OACZsB,qBACAC,WACAC,wBAKA,MAAMC,EAAQjB,EAAWkB,GACnBC,EAAmBC,EAAW,UAAU,CAAEH,UAC1CI,EAAaC,EAA8B,OACzCC,MAAOC,EAAiB,GAAMC,EAAkB,CACpDC,UAAWV,QAAAA,EAAeK,EAC1BM,cAAc,IAEZC,EAAqB,CACvBC,KAAM,SACNC,GAAI,EAAGC,IAAGC,YACN,MAAMC,EACI,IAANF,GAAWA,EAAIC,EAAME,SAASX,QAAUY,OAAOC,WAC7CC,EAAiBF,OAAOC,WAAajB,EAC3C,MAAO,CACHY,EACIE,GAAkBI,GACXF,OAAOC,WAAaJ,EAAME,SAASX,OAAS,EAC7CQ,EACb,IAGHO,KAAEA,EAAIC,eAAEA,EAAcC,QAAEA,GAAYC,EAAY,CAClDC,KAAMvC,EACNwC,aAAc,CAACD,EAAME,EAAQC,KACV,eAAXA,EACAvC,SAAAA,IACOoC,IAASvC,EAChBC,SAAAA,KACQsC,GAAQvC,IAChBE,SAAAA,EAAUwC,GACd,EAEJC,qBAAsBC,EACtBC,UAAWzD,EAAqBC,GAChCyD,WAAY,CACRrC,EAAOC,GACPqC,IACAC,EAAM,CACFC,QAASC,MAEbC,EAAK,CAED,KAAAC,EAAMC,gBAAEA,EAAeC,SAAEA,KAEhB3C,GACD0C,GAAmBC,EAASvB,SAASwB,aAGrCD,EAASvB,SAASyB,MAAMC,YACpB,qBACA,IAKRH,EAASvB,SAASyB,MAAMC,YACpB,qBACA,GAAGC,KAAKC,IAAI,EAAGN,OAEvB,IAEJ5B,KAGFmC,EAAeC,KAEfC,UAAEA,EAASrE,OAAEA,GAAWsE,EAAoB1B,EAAS,CACvD2B,QAAS,CAAEC,QAAS,GACpB1B,KAAM,CAAE0B,QAAS,GACjBC,SAAU,MAGRC,GAAQC,EAAS/B,EAAS,CAC5BtC,UACAsE,OAAQ7D,EACR8D,iBAAkB9D,IAEhB+D,GAAUC,EAAWnC,EAAS,CAAEtC,aAEhC0E,kBAAEA,GAAiB9E,iBAAEA,IAAqB+E,EAAgB,CAC5DP,GACAI,KAMEI,GAAgBC,EAAYd,GAC5Be,GAAcC,GAAS,IAAM1E,aAAM,EAANA,MAEnC2E,GAAU,KACFJ,KAAkBb,GAClBe,IACJ,GACD,CAACF,GAAeb,EAAWe,KAK9B,MAAMG,GAAsB,CACxBxF,aAAc6B,EACd5B,oDACOA,GACA2C,GAAc,CACjB6C,OAAoC,QAA5BC,EAAA3E,QAAAA,EAAgBqD,SAAY,IAAAsB,EAAAA,EAzKxB,KA2KhBxF,eAAgByC,EAAKgD,YACrBxF,qBAGJ,OACIyF,eACIC,EAAA,MAAAC,OAAAC,OAAA,CACIC,IAAMC,IACFvE,EAAWwE,QAAUD,EACrBtD,EAAKwD,aAAaF,EAAK,GAEvBhB,KAAmB,CAAAmB,SAEtBvF,OAEJyD,GACGuB,EAACQ,GAAeC,KAAMlF,EAAQgF,SAC1BP,EAACU,EAAoB,CACjB1D,QAASA,EACT2D,OAAO,EACPC,cAAc,EACdC,aAAa,EAAKN,SAElBP,EAAC/F,EAAsB6G,SAAQ,CAC3BC,MAAOpB,GAAmBY,SAEzBtF,EAAe0E,YAKjC"}
@@ -1,15 +1,13 @@
1
- import e from"styled-components";import{Colour as r,Border as o,Radius as d,Spacing as t}from"../theme/index.js";const i=r.border,l=r.text,a=e.div`
1
+ import e from"styled-components";import{Colour as r,Border as o,Radius as i,Spacing as t}from"../theme/index.js";const d=r.border,l=r.text,a=e.div`
2
2
  overflow: auto;
3
- border: ${o["width-010"]} ${o.solid} ${i};
4
- border-radius: ${d.md};
3
+ border: ${o["width-010"]} ${o.solid} ${d};
4
+ border-radius: ${i.md};
5
5
 
6
- // Hide scrollbar
6
+ /* Hide scrollbar */
7
+ scrollbar-width: none; /* Firefox */
8
+ -ms-overflow-style: none; /* IE 10+ */
7
9
  &::-webkit-scrollbar {
8
- display: none;
9
- }
10
- * {
11
- -ms-overflow-style: none; /* IE and Edge */
12
- scrollbar-width: none; /* Firefox */
10
+ display: none; /* Chrome/Safari/Webkit */
13
11
  }
14
12
  `;a.displayName="Table.Container";const n=e.table`
15
13
  text-align: left;
@@ -30,7 +28,7 @@ import e from"styled-components";import{Colour as r,Border as o,Radius as d,Spac
30
28
  color: ${l};
31
29
  background-color: ${r["bg-stronger"]};
32
30
  height: 6rem;
33
- border-bottom: ${o["width-010"]} ${o.solid} ${i};
31
+ border-bottom: ${o["width-010"]} ${o.solid} ${d};
34
32
 
35
33
  &:where(&:first-child) {
36
34
  padding-left: ${t["spacing-24"]};
@@ -40,12 +38,12 @@ import e from"styled-components";import{Colour as r,Border as o,Radius as d,Spac
40
38
  }
41
39
  `,g=e.tr`
42
40
  background-color: ${r.bg};
43
- border-top: ${o["width-010"]} ${o.solid} ${i};
41
+ border-top: ${o["width-010"]} ${o.solid} ${d};
44
42
  `,b=e.td`
45
43
  padding: ${t["spacing-20"]} ${t["spacing-16"]};
46
44
  vertical-align: middle;
47
45
  color: ${l};
48
- border-bottom: ${o["width-010"]} ${o.solid} ${i};
46
+ border-bottom: ${o["width-010"]} ${o.solid} ${d};
49
47
 
50
48
  &:where(&:first-child) {
51
49
  padding-left: ${t["spacing-24"]};
@@ -1 +1 @@
1
- {"version":3,"file":"table.styles.js","sources":["../../src/table/table.styles.tsx"],"sourcesContent":["import styled from \"styled-components\";\nimport { Border, Colour, Radius, Spacing } from \"../theme\";\n\n// =============================================================================\n// STYLES CONSTANTS\n// =============================================================================\nconst borderColor = Colour[\"border\"];\nconst fontColor = Colour[\"text\"];\n\n// =============================================================================\n// STYLES\n// =============================================================================\nexport const TableWrapper = styled.div`\n overflow: auto;\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n border-radius: ${Radius[\"md\"]};\n\n // Hide scrollbar\n &::-webkit-scrollbar {\n display: none;\n }\n * {\n -ms-overflow-style: none; /* IE and Edge */\n scrollbar-width: none; /* Firefox */\n }\n`;\n\nTableWrapper.displayName = \"Table.Container\";\n\nexport const TableComponent = styled.table`\n text-align: left;\n border-collapse: separate;\n border-spacing: 0;\n width: 100%;\n`;\n\nTableComponent.displayName = \"Table.Table\";\n\nexport const TableBody = styled.tbody`\n :where(tr:last-child) {\n td {\n border-bottom: none;\n }\n }\n`;\n\nexport const HeaderCell = styled.th`\n padding: ${Spacing[\"spacing-20\"]} ${Spacing[\"spacing-16\"]};\n text-align: left;\n cursor: default;\n vertical-align: middle;\n color: ${fontColor};\n background-color: ${Colour[\"bg-stronger\"]};\n height: 6rem;\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n\n &:where(&:first-child) {\n padding-left: ${Spacing[\"spacing-24\"]};\n }\n &:where(&:last-child) {\n padding-right: ${Spacing[\"spacing-24\"]};\n }\n`;\n\nexport const BodyRow = styled.tr`\n background-color: ${Colour[\"bg\"]};\n border-top: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n`;\n\nexport const BodyCell = styled.td`\n padding: ${Spacing[\"spacing-20\"]} ${Spacing[\"spacing-16\"]};\n vertical-align: middle;\n color: ${fontColor};\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n\n &:where(&:first-child) {\n padding-left: ${Spacing[\"spacing-24\"]};\n }\n &:where(&:last-child) {\n padding-right: ${Spacing[\"spacing-24\"]};\n }\n`;\n"],"names":["borderColor","Colour","fontColor","TableWrapper","styled","div","Border","Radius","displayName","TableComponent","table","TableBody","tbody","HeaderCell","th","Spacing","BodyRow","tr","BodyCell","td"],"mappings":"iHAMA,MAAMA,EAAcC,EAAe,OAC7BC,EAAYD,EAAa,KAKlBE,EAAeC,EAAOC,GAAG;;cAExBC,EAAO,gBAAgBA,EAAc,SAAKN;qBACnCO,EAAW;;;;;;;;;;EAYhCJ,EAAaK,YAAc,kBAEpB,MAAMC,EAAiBL,EAAOM,KAAK;;;;;EAO1CD,EAAeD,YAAc,cAEtB,MAAMG,EAAYP,EAAOQ,KAAK;;;;;;EAQxBC,EAAaT,EAAOU,EAAE;eACpBC,EAAQ,iBAAiBA,EAAQ;;;;aAInCb;wBACWD,EAAO;;qBAEVK,EAAO,gBAAgBA,EAAc,SAAKN;;;wBAGvCe,EAAQ;;;yBAGPA,EAAQ;;EAIpBC,EAAUZ,EAAOa,EAAE;wBACRhB,EAAW;kBACjBK,EAAO,gBAAgBA,EAAc,SAAKN;EAG/CkB,EAAWd,EAAOe,EAAE;eAClBJ,EAAQ,iBAAiBA,EAAQ;;aAEnCb;qBACQI,EAAO,gBAAgBA,EAAc,SAAKN;;;wBAGvCe,EAAQ;;;yBAGPA,EAAQ;;"}
1
+ {"version":3,"file":"table.styles.js","sources":["../../src/table/table.styles.tsx"],"sourcesContent":["import styled from \"styled-components\";\nimport { Border, Colour, Radius, Spacing } from \"../theme\";\n\n// =============================================================================\n// STYLES CONSTANTS\n// =============================================================================\nconst borderColor = Colour[\"border\"];\nconst fontColor = Colour[\"text\"];\n\n// =============================================================================\n// STYLES\n// =============================================================================\nexport const TableWrapper = styled.div`\n overflow: auto;\n border: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n border-radius: ${Radius[\"md\"]};\n\n /* Hide scrollbar */\n scrollbar-width: none; /* Firefox */\n -ms-overflow-style: none; /* IE 10+ */\n &::-webkit-scrollbar {\n display: none; /* Chrome/Safari/Webkit */\n }\n`;\n\nTableWrapper.displayName = \"Table.Container\";\n\nexport const TableComponent = styled.table`\n text-align: left;\n border-collapse: separate;\n border-spacing: 0;\n width: 100%;\n`;\n\nTableComponent.displayName = \"Table.Table\";\n\nexport const TableBody = styled.tbody`\n :where(tr:last-child) {\n td {\n border-bottom: none;\n }\n }\n`;\n\nexport const HeaderCell = styled.th`\n padding: ${Spacing[\"spacing-20\"]} ${Spacing[\"spacing-16\"]};\n text-align: left;\n cursor: default;\n vertical-align: middle;\n color: ${fontColor};\n background-color: ${Colour[\"bg-stronger\"]};\n height: 6rem;\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n\n &:where(&:first-child) {\n padding-left: ${Spacing[\"spacing-24\"]};\n }\n &:where(&:last-child) {\n padding-right: ${Spacing[\"spacing-24\"]};\n }\n`;\n\nexport const BodyRow = styled.tr`\n background-color: ${Colour[\"bg\"]};\n border-top: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n`;\n\nexport const BodyCell = styled.td`\n padding: ${Spacing[\"spacing-20\"]} ${Spacing[\"spacing-16\"]};\n vertical-align: middle;\n color: ${fontColor};\n border-bottom: ${Border[\"width-010\"]} ${Border[\"solid\"]} ${borderColor};\n\n &:where(&:first-child) {\n padding-left: ${Spacing[\"spacing-24\"]};\n }\n &:where(&:last-child) {\n padding-right: ${Spacing[\"spacing-24\"]};\n }\n`;\n"],"names":["borderColor","Colour","fontColor","TableWrapper","styled","div","Border","Radius","displayName","TableComponent","table","TableBody","tbody","HeaderCell","th","Spacing","BodyRow","tr","BodyCell","td"],"mappings":"iHAMA,MAAMA,EAAcC,EAAe,OAC7BC,EAAYD,EAAa,KAKlBE,EAAeC,EAAOC,GAAG;;cAExBC,EAAO,gBAAgBA,EAAc,SAAKN;qBACnCO,EAAW;;;;;;;;EAUhCJ,EAAaK,YAAc,kBAEpB,MAAMC,EAAiBL,EAAOM,KAAK;;;;;EAO1CD,EAAeD,YAAc,cAEtB,MAAMG,EAAYP,EAAOQ,KAAK;;;;;;EAQxBC,EAAaT,EAAOU,EAAE;eACpBC,EAAQ,iBAAiBA,EAAQ;;;;aAInCb;wBACWD,EAAO;;qBAEVK,EAAO,gBAAgBA,EAAc,SAAKN;;;wBAGvCe,EAAQ;;;yBAGPA,EAAQ;;EAIpBC,EAAUZ,EAAOa,EAAE;wBACRhB,EAAW;kBACjBK,EAAO,gBAAgBA,EAAc,SAAKN;EAG/CkB,EAAWd,EAAOe,EAAE;eAClBJ,EAAQ,iBAAiBA,EAAQ;;aAEnCb;qBACQI,EAAO,gBAAgBA,EAAc,SAAKN;;;wBAGvCe,EAAQ;;;yBAGPA,EAAQ;;"}
package/util/index.d.ts CHANGED
@@ -13,4 +13,5 @@ export * from "./use-mount";
13
13
  export * from "./use-next-input-state";
14
14
  export * from "./use-previous";
15
15
  export * from "./use-state-ref";
16
+ export * from "./use-throttle";
16
17
  export * from "./version";
@@ -0,0 +1 @@
1
+ export declare function useThrottle<T extends (...args: any[]) => any>(callback: T, wait: number): T;
@@ -0,0 +1,2 @@
1
+ import{useRef as r,useEffect as t,useCallback as n}from"react";function e(e,u){const c=r(e),l=r(0),o=r(null);return t((()=>{c.current=e}),[e]),t((()=>()=>{null!==o.current&&clearTimeout(o.current)}),[]),n(((...r)=>{const t=Date.now(),n=t-l.current;null!==o.current&&(clearTimeout(o.current),o.current=null),n>=u?(l.current=t,c.current(...r)):o.current=setTimeout((()=>{l.current=Date.now(),o.current=null,c.current(...r)}),u-n)}),[u])}export{e as useThrottle};
2
+ //# sourceMappingURL=use-throttle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-throttle.js","sources":["../../src/util/use-throttle.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from \"react\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function useThrottle<T extends (...args: any[]) => any>(\n callback: T,\n wait: number\n): T {\n const callbackRef = useRef<T>(callback);\n const lastCalledRef = useRef<number>(0);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current !== null) {\n clearTimeout(timeoutRef.current);\n }\n };\n }, []);\n\n return useCallback(\n (...args: Parameters<T>) => {\n const now = Date.now();\n const elapsed = now - lastCalledRef.current;\n\n if (timeoutRef.current !== null) {\n clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n\n if (elapsed >= wait) {\n lastCalledRef.current = now;\n callbackRef.current(...args);\n } else {\n timeoutRef.current = setTimeout(() => {\n lastCalledRef.current = Date.now();\n timeoutRef.current = null;\n callbackRef.current(...args);\n }, wait - elapsed);\n }\n },\n [wait]\n ) as T;\n}\n"],"names":["useThrottle","callback","wait","callbackRef","useRef","lastCalledRef","timeoutRef","useEffect","current","clearTimeout","useCallback","args","now","Date","elapsed","setTimeout"],"mappings":"+DAGM,SAAUA,EACZC,EACAC,GAEA,MAAMC,EAAcC,EAAUH,GACxBI,EAAgBD,EAAe,GAC/BE,EAAaF,EAA6C,MAchE,OAZAG,GAAU,KACNJ,EAAYK,QAAUP,CAAQ,GAC/B,CAACA,IAEJM,GAAU,IACC,KACwB,OAAvBD,EAAWE,SACXC,aAAaH,EAAWE,QAC5B,GAEL,IAEIE,GACH,IAAIC,KACA,MAAMC,EAAMC,KAAKD,MACXE,EAAUF,EAAMP,EAAcG,QAET,OAAvBF,EAAWE,UACXC,aAAaH,EAAWE,SACxBF,EAAWE,QAAU,MAGrBM,GAAWZ,GACXG,EAAcG,QAAUI,EACxBT,EAAYK,WAAWG,IAEvBL,EAAWE,QAAUO,YAAW,KAC5BV,EAAcG,QAAUK,KAAKD,MAC7BN,EAAWE,QAAU,KACrBL,EAAYK,WAAWG,EAAK,GAC7BT,EAAOY,EACd,GAEJ,CAACZ,GAET"}