@lifesg/react-design-system 4.0.0-alpha.8 → 4.0.0-alpha.9

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 (199) hide show
  1. package/accordion/accordion-item.js.map +1 -1
  2. package/accordion/accordion.js.map +1 -1
  3. package/alert/alert.js.map +1 -1
  4. package/cjs/accordion/accordion-item.js.map +1 -1
  5. package/cjs/accordion/accordion.js.map +1 -1
  6. package/cjs/alert/alert.js.map +1 -1
  7. package/cjs/countdown-timer/countdown-timer.js.map +1 -1
  8. package/cjs/data-table/data-table.js +1 -1
  9. package/cjs/data-table/data-table.js.map +1 -1
  10. package/cjs/date-range-input/date-range-input.js.map +1 -1
  11. package/cjs/e-signature/e-signature-canvas.js.map +1 -1
  12. package/cjs/error-display/inactivity-timer.js.map +1 -1
  13. package/cjs/external/dompurify/dist/purify.es.js +2 -2
  14. package/cjs/external/dompurify/dist/purify.es.js.map +1 -1
  15. package/cjs/file-download/file-list-card/file-list-card.js.map +1 -1
  16. package/cjs/file-upload/custom-sensors.js.map +1 -1
  17. package/cjs/file-upload/file-list/file-list.js.map +1 -1
  18. package/cjs/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  19. package/cjs/filter/addons/filter-item-checkbox.js.map +1 -1
  20. package/cjs/filter/filter-item.js.map +1 -1
  21. package/cjs/filter/filter.js.map +1 -1
  22. package/cjs/form/form-textarea/form-textarea.js +1 -1
  23. package/cjs/form/form-textarea/form-textarea.js.map +1 -1
  24. package/cjs/fullscreen-image-carousel/stateful-image.js.map +1 -1
  25. package/cjs/histogram-slider/histogram-slider.js.map +1 -1
  26. package/cjs/input-range-slider/input-range-slider.js.map +1 -1
  27. package/cjs/input-slider/input-slider.js.map +1 -1
  28. package/cjs/input-textarea/textarea-counter.js.map +1 -1
  29. package/cjs/input-textarea/textarea.js +1 -1
  30. package/cjs/input-textarea/textarea.js.map +1 -1
  31. package/cjs/input-textarea/textarea.styles.js +1 -1
  32. package/cjs/input-textarea/textarea.styles.js.map +1 -1
  33. package/{input-textarea/textarea.styles_q77m5x.css → cjs/input-textarea/textarea.styles_6we7bs.css} +3 -1
  34. package/cjs/modal/index.js.map +1 -1
  35. package/cjs/modal-v2/modal-v2.js +1 -1
  36. package/cjs/modal-v2/modal-v2.js.map +1 -1
  37. package/cjs/modal-v2/slots/card.js +1 -1
  38. package/cjs/modal-v2/slots/card.js.map +1 -1
  39. package/cjs/modal-v2/slots/header.js +2 -0
  40. package/cjs/modal-v2/slots/header.js.map +1 -0
  41. package/cjs/modal-v2/slots/slot-styles.js +1 -1
  42. package/cjs/modal-v2/slots/slot-styles.js.map +1 -1
  43. package/cjs/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
  44. package/cjs/navbar/navbar-items.js +1 -1
  45. package/cjs/navbar/navbar-items.js.map +1 -1
  46. package/cjs/navbar/navbar-items.styles.js +1 -1
  47. package/cjs/navbar/navbar-items.styles.js.map +1 -1
  48. package/cjs/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
  49. package/cjs/navbar/navbar-logo-data.js +1 -1
  50. package/cjs/navbar/navbar-logo-data.js.map +1 -1
  51. package/cjs/navbar/navbar.js.map +1 -1
  52. package/cjs/otp-input/otp-input.js.map +1 -1
  53. package/cjs/overlay/overlay.js.map +1 -1
  54. package/cjs/pagination/pagination.js.map +1 -1
  55. package/cjs/phone-number-input/phone-number-input.js.map +1 -1
  56. package/cjs/predictive-text-input/predictive-text-input.js.map +1 -1
  57. package/cjs/shared/dropdown-list/dropdown-list.js.map +1 -1
  58. package/cjs/shared/internal-calendar/calendar-manager.js.map +1 -1
  59. package/cjs/shared/standalone-date-input/standalone-date-input.js.map +1 -1
  60. package/cjs/theme/types.js +1 -1
  61. package/cjs/theme/types.js.map +1 -1
  62. package/cjs/time-slot-bar/time-slot-bar.js.map +1 -1
  63. package/cjs/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
  64. package/cjs/timetable/timetable.js.map +1 -1
  65. package/cjs/toggle/toggle-icon.js +1 -1
  66. package/cjs/toggle/toggle-icon.js.map +1 -1
  67. package/cjs/toggle/toggle-icon.styles.js +1 -1
  68. package/cjs/toggle/toggle-icon.styles.js.map +1 -1
  69. package/cjs/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
  70. package/cjs/toggle/toggle.js +1 -1
  71. package/cjs/toggle/toggle.js.map +1 -1
  72. package/cjs/toggle/toggle.styles.js +1 -1
  73. package/cjs/toggle/toggle.styles.js.map +1 -1
  74. package/cjs/toggle/toggle.styles_11tmfsr.css +41 -0
  75. package/cjs/unit-number/unit-number-input.js.map +1 -1
  76. package/cjs/util/is-styled-components.js.map +1 -1
  77. package/cjs/util/string-helper.js +1 -1
  78. package/cjs/util/string-helper.js.map +1 -1
  79. package/cjs/util/use-event-listener.js.map +1 -1
  80. package/cjs/util/use-state-actions.js.map +1 -1
  81. package/countdown-timer/countdown-timer.js.map +1 -1
  82. package/data-table/data-table.js +1 -1
  83. package/data-table/data-table.js.map +1 -1
  84. package/data-table/types.d.ts +2 -2
  85. package/date-range-input/date-range-input.js.map +1 -1
  86. package/docs/component-catalog.json +1 -1
  87. package/e-signature/e-signature-canvas.js.map +1 -1
  88. package/error-display/inactivity-timer.js.map +1 -1
  89. package/external/dompurify/dist/purify.es.js +2 -2
  90. package/external/dompurify/dist/purify.es.js.map +1 -1
  91. package/file-download/file-list-card/file-list-card.js.map +1 -1
  92. package/file-upload/custom-sensors.d.ts +2 -2
  93. package/file-upload/custom-sensors.js.map +1 -1
  94. package/file-upload/file-list/file-list.js.map +1 -1
  95. package/filter/addons/filter-item-checkbox-helpers.js.map +1 -1
  96. package/filter/addons/filter-item-checkbox.js.map +1 -1
  97. package/filter/filter-item.js.map +1 -1
  98. package/filter/filter.js.map +1 -1
  99. package/form/form-textarea/form-textarea.js +1 -1
  100. package/form/form-textarea/form-textarea.js.map +1 -1
  101. package/fullscreen-image-carousel/stateful-image.js.map +1 -1
  102. package/fullscreen-image-carousel/types.d.ts +2 -2
  103. package/histogram-slider/histogram-slider.js.map +1 -1
  104. package/input-range-slider/input-range-slider.js.map +1 -1
  105. package/input-slider/input-slider.js.map +1 -1
  106. package/input-textarea/textarea-counter.js.map +1 -1
  107. package/input-textarea/textarea.js +1 -1
  108. package/input-textarea/textarea.js.map +1 -1
  109. package/input-textarea/textarea.styles.d.ts +2 -0
  110. package/input-textarea/textarea.styles.js +1 -1
  111. package/input-textarea/textarea.styles.js.map +1 -1
  112. package/{cjs/input-textarea/textarea.styles_q77m5x.css → input-textarea/textarea.styles_6we7bs.css} +3 -1
  113. package/input-textarea/types.d.ts +7 -0
  114. package/modal/index.d.ts +4 -0
  115. package/modal/index.js.map +1 -1
  116. package/modal/types.d.ts +2 -0
  117. package/modal-v2/modal-v2.d.ts +6 -0
  118. package/modal-v2/modal-v2.js +1 -1
  119. package/modal-v2/modal-v2.js.map +1 -1
  120. package/modal-v2/slots/card.js +1 -1
  121. package/modal-v2/slots/card.js.map +1 -1
  122. package/modal-v2/slots/header.d.ts +5 -0
  123. package/modal-v2/slots/header.js +2 -0
  124. package/modal-v2/slots/header.js.map +1 -0
  125. package/modal-v2/slots/index.d.ts +1 -0
  126. package/modal-v2/slots/slot-styles.d.ts +4 -0
  127. package/modal-v2/slots/slot-styles.js +1 -1
  128. package/modal-v2/slots/slot-styles.js.map +1 -1
  129. package/modal-v2/slots/{slot-styles_13sd376.css → slot-styles_10ut1v7.css} +5 -1
  130. package/modal-v2/types.d.ts +21 -0
  131. package/navbar/navbar-items.js +1 -1
  132. package/navbar/navbar-items.js.map +1 -1
  133. package/navbar/navbar-items.styles.d.ts +2 -1
  134. package/navbar/navbar-items.styles.js +1 -1
  135. package/navbar/navbar-items.styles.js.map +1 -1
  136. package/navbar/{navbar-items.styles_1i3ltot.css → navbar-items.styles_1b1zx.css} +9 -8
  137. package/navbar/navbar-logo-data.js +1 -1
  138. package/navbar/navbar-logo-data.js.map +1 -1
  139. package/navbar/navbar.js.map +1 -1
  140. package/otp-input/otp-input.js.map +1 -1
  141. package/overlay/overlay.js.map +1 -1
  142. package/package.json +1 -1
  143. package/pagination/pagination.js.map +1 -1
  144. package/phone-number-input/phone-number-input.js.map +1 -1
  145. package/predictive-text-input/predictive-text-input.js.map +1 -1
  146. package/shared/dropdown-list/dropdown-list.js.map +1 -1
  147. package/shared/internal-calendar/calendar-manager.js.map +1 -1
  148. package/shared/standalone-date-input/standalone-date-input.js.map +1 -1
  149. package/theme/styles/a11y-playground.css +358 -87
  150. package/theme/styles/bookingsg.css +391 -85
  151. package/theme/styles/careercompass.css +396 -90
  152. package/theme/styles/ccube.css +402 -45
  153. package/theme/styles/imda.css +348 -85
  154. package/theme/styles/lifesg.css +377 -87
  155. package/theme/styles/mylegacy.css +382 -85
  156. package/theme/styles/oneservice.css +349 -86
  157. package/theme/styles/pa.css +172 -63
  158. package/theme/styles/rbs.css +403 -46
  159. package/theme/styles/sgw-digital-lobby.css +352 -87
  160. package/theme/styles/smgs.css +401 -95
  161. package/theme/styles/spf.css +208 -99
  162. package/theme/styles/supportgowhere.css +387 -90
  163. package/theme/styles/tote-board.css +816 -0
  164. package/theme/types.d.ts +1 -1
  165. package/theme/types.js +1 -1
  166. package/theme/types.js.map +1 -1
  167. package/time-slot-bar/time-slot-bar.js.map +1 -1
  168. package/time-slot-bar-week/time-slot-bar-week-days.js.map +1 -1
  169. package/timetable/timetable.js.map +1 -1
  170. package/toggle/toggle-icon.d.ts +2 -1
  171. package/toggle/toggle-icon.js +1 -1
  172. package/toggle/toggle-icon.js.map +1 -1
  173. package/toggle/toggle-icon.styles.d.ts +1 -0
  174. package/toggle/toggle-icon.styles.js +1 -1
  175. package/toggle/toggle-icon.styles.js.map +1 -1
  176. package/toggle/{toggle-icon.styles_ba71y.css → toggle-icon.styles_o6dxr3.css} +3 -2
  177. package/toggle/toggle.js +1 -1
  178. package/toggle/toggle.js.map +1 -1
  179. package/toggle/toggle.styles.d.ts +18 -15
  180. package/toggle/toggle.styles.js +1 -1
  181. package/toggle/toggle.styles.js.map +1 -1
  182. package/toggle/toggle.styles_11tmfsr.css +41 -0
  183. package/unit-number/unit-number-input.js.map +1 -1
  184. package/util/is-styled-components.js.map +1 -1
  185. package/util/string-helper.d.ts +2 -2
  186. package/util/string-helper.js +1 -1
  187. package/util/string-helper.js.map +1 -1
  188. package/util/use-event-listener.js.map +1 -1
  189. package/util/use-state-actions.js.map +1 -1
  190. package/cjs/form/form-textarea/form-textarea.styles.js +0 -2
  191. package/cjs/form/form-textarea/form-textarea.styles.js.map +0 -1
  192. package/cjs/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
  193. package/cjs/toggle/toggle.styles_1t5qrye.css +0 -38
  194. package/form/form-textarea/form-textarea.styles.d.ts +0 -3
  195. package/form/form-textarea/form-textarea.styles.js +0 -2
  196. package/form/form-textarea/form-textarea.styles.js.map +0 -1
  197. package/form/form-textarea/form-textarea.styles_1kneyif.css +0 -3
  198. package/theme/styles/default.css +0 -158
  199. package/toggle/toggle.styles_1t5qrye.css +0 -38
package/toggle/toggle.js CHANGED
@@ -1,2 +1,2 @@
1
- import{__rest as e}from"../_virtual/_tslib.js";import{jsxs as i,jsx as t,Fragment as r}from"react/jsx-runtime";import{ChevronDownIcon as l}from"@lifesg/react-icons/chevron-down";import{ChevronUpIcon as o}from"@lifesg/react-icons/chevron-up";import a from"clsx";import{useState as s,useMemo as n,useRef as d,useEffect as c}from"react";import{Alert as m}from"../alert/alert.js";import{Markup as p}from"../markup/markup.js";import{TextList as h}from"../text-list/index.js";import"../theme/theme-provider/index.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as u}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as b}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as v}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{tokens as y,container as f,noIndicatorContainer as g,useContentWidthContainer as k,headerContainer as j,inputContainer as x,input as N,toggleInputDisabled as $,label as C,toggleLabelSelected as w,toggleLabelDefault as L,textContainer as A,indicatorLabelContainer as D,indicatorLabelContainerAddPadding as S,removeButton as M,disabledColorCursor as W,colorBorderError as B,toggleContainerError as R,toggleContainerNoBorderDisabledSelected as T,toggleContainerNoBorderDisabled as q,toggleContainerNoBorderSelected as E,toggleContainerNoBorder as I,toggleContainerDisabledSelected as _,toggleContainerDisabled as z,toggleContainerSelected as F,toggleContainer as O,toggleContainerHoverSelected as P,toggleContainerHoverDefault as U,subLabel as G,toggleTextContainerDisabledSelected as H,colorTextDisabled as J,toggleTextContainerSelected as K,children as Q,childrenIsFinalItem as V,alertContainer as X,errorContainer as Y,expandButton as Z,expandButtonPaddingTopRequired as ee,colorTextError as ie}from"./toggle.styles.js";import{ToggleIcon as te}from"./toggle-icon.js";const re=re=>{var{type:le="checkbox",indicator:oe,checked:ae,styleType:se="default",children:ne,childrenMaxLines:de,subLabel:ce,disabled:me,error:pe,name:he,id:ue,className:be,compositeSection:ve,removable:ye,focusableWhenDisabled:fe,useContentWidth:ge,onRemove:ke,onChange:je,"data-testid":xe,"aria-describedby":Ne}=re,$e=e(re,["type","indicator","checked","styleType","children","childrenMaxLines","subLabel","disabled","error","name","id","className","compositeSection","removable","focusableWhenDisabled","useContentWidth","onRemove","onChange","data-testid","aria-describedby"]);const{collapsible:Ce=!0,errors:we,children:Le,initialExpanded:Ae}=ve||{},[De,Se]=s(ae),[Me,We]=s(!!Ae),Be=n((()=>{const e=Array.isArray(we)&&(null==we?void 0:we.length)>0,i=!Array.isArray(we)&&!!we;return e||i}),[we]),Re=v(),Te=ue?`${ue}`:`tg-${Re}`,qe=d(null),Ee=d(null);u(Ee,{[y.label.desktopLineClamp]:null==(null==de?void 0:de.desktop)?null:`${de.desktop}`,[y.label.tabletLineClamp]:null==(null==de?void 0:de.tablet)?null:`${de.tablet}`,[y.label.mobileLineClamp]:null==(null==de?void 0:de.mobile)?null:`${de.mobile}`});const Ie=!!me&&!!fe,_e=!!me&&!fe,ze=!!me;c((()=>{Se(ae)}),[ae]),c((()=>{De&&We(null==Ae||Ae)}),[De]);const Fe=e=>{if(ze)e.preventDefault();else if(je)je(e);else switch(le){case"checkbox":Se((e=>!e));break;case"radio":case"yes":case"no":De||Se(!0)}},Oe=()=>{me||We(!Me)},Pe=()=>{me||!ke||ke()},Ue=()=>{var e;null===(e=null==qe?void 0:qe.current)||void 0===e||e.click()},Ge=e=>{e.stopPropagation()},He=()=>{let e;switch(le){case"yes":e="tick";break;case"no":e="cross";break;case"checkbox":case"radio":e=le}return t(te,{type:e,active:De,disabled:me})},Je=()=>{if(!ce)return null;let e;return e="function"==typeof ce?ce():ce,t("div",{"data-id":"toggle-sublabel",id:`${Te}-sublabel`,"aria-hidden":!0,className:G,children:e})},Ke=e=>i(r,{children:[t(b.BodyMD,{weight:"semibold",className:a(ie,me&&J),children:"Error"}),t(h.Ul,{className:a(ie,me&&J),children:null==e?void 0:e.map(((e,i)=>t("li",{id:`${Te}-error-list-item-${i}`,children:t(b.BodyMD,{weight:"semibold",className:a(ie,me&&J),children:e})},i)))})]});return i("div",{className:a(f,"no-border"===se?pe?a(B,!me&&R):me?De?T:q:De?E:I:pe?me?B:R:me?De?_:z:De?F:O,(()=>{if(!me)return!pe&&De?P:U})(),!oe&&g,ge&&k,be),id:ue,"data-testid":xe,children:[(()=>{const e=["string"==typeof ce?`${Te}-sublabel`:null,Ne].filter(Boolean).join(" ")||void 0;return i("div",{id:`${Te}-header-container`,className:j,children:[t("div",{className:a(D,ye&&S),children:i("div",{id:`${Te}-input-container`,onClick:Ue,className:x,children:[t("input",Object.assign({ref:qe,name:he,id:`${Te}-input`,type:"checkbox"===le?"checkbox":"radio","data-testid":"toggle-input",className:a(N,me&&$),disabled:_e,"aria-disabled":Ie,onChange:Fe,onClick:Ge,checked:De,tabIndex:Ie?0:void 0,"aria-describedby":e},$e)),oe&&He(),i("div",{className:a(A,me?De?H:J:De?K:void 0),children:[t("label",{ref:Ee,htmlFor:`${Te}-input`,"data-testid":"toggle-label",id:`${Te}-label`,className:a(C,De?w:L),children:ne}),ce&&Je()]})]})}),ye&&t("button",{type:"button",className:a(M,me&&W),onClick:Pe,id:`${Te}-remove-button`,children:"Remove"})]})})(),Le&&i("div",{children:[(!Ce||Me)&&t("div",{"data-id":"toggle-composite-children",className:a(Q,!Ce&&V,me&&J),children:t(p,{baseTextSize:"body-md",children:Le})}),Ce&&!Me&&Be&&t("div",{className:a(Y,me&&W),onClick:Oe,id:`${Te}-error-alert`,children:t(m,{type:me?"description":"error",className:X,showIcon:!0,children:Array.isArray(we)?Ke(we):we})}),Ce&&i("button",{className:a(Z,me&&W,!Me&&!Be&&ee),disabled:me,onClick:Oe,"data-testid":Me?"collapse-button":"expand-button",children:[Me?"Show less":"Show more",t(Me?o:l,{"aria-hidden":!0})]})]})]})};export{re as Toggle};
1
+ import{__rest as e}from"../_virtual/_tslib.js";import{jsxs as i,jsx as r,Fragment as t}from"react/jsx-runtime";import{ChevronDownIcon as l}from"@lifesg/react-icons/chevron-down";import{ChevronUpIcon as o}from"@lifesg/react-icons/chevron-up";import a from"clsx";import{useState as s,useMemo as n,useRef as d,useEffect as c}from"react";import{Alert as m}from"../alert/alert.js";import{Markup as p}from"../markup/markup.js";import{TextList as h}from"../text-list/index.js";import"../theme/theme-provider/index.js";import"../theme/theme-provider/context.js";import"../theme/tokens/border.js";import"../theme/tokens/colour.js";import"../theme/tokens/font.js";import"../theme/tokens/media-query.js";import{useApplyStyle as u}from"../theme/utils/use-apply-styles.js";import"../theme/utils/use-media-query.js";import{Typography as b}from"../typography/index.js";import"../util/calendar-helper.js";import"../external/dayjs/dayjs.min.js";import{useId as y}from"../util/simple-id-generator.js";import"../util/string-helper.js";import"@react-aria/live-announcer";import{tokens as v,container as f,containerNoIndicator as g,containerUseContentWidth as k,headerContainer as j,inputContainer as x,input as N,disabledColorCursor as $,label as C,toggleLabelSelected as w,toggleLabelDefault as L,textContainer as A,indicatorLabelContainer as D,indicatorLabelContainerAddPadding as S,removeButton as M,borderError as W,borderNone as B,borderSelectedDisabled as R,borderDisabled as T,borderSelected as q,borderDefault as E,bgError as I,bgSelectedDisabled as _,bgSelected as z,bgDisabled as F,bgDefault as O,toggleContainerHoverError as P,toggleContainerHoverSelected as U,toggleContainerHoverDefault as G,subLabel as H,colorTextError as J,toggleTextContainerDisabledSelected as K,toggleTextContainerSelected as Q,colorTextDisabled as V,colorTextDefault as X,children as Y,childrenIsFinalItem as Z,alertContainer as ee,errorContainer as ie,expandButton as re,colorTextPrimary as te,expandButtonPaddingTopRequired as le}from"./toggle.styles.js";import{ToggleIcon as oe}from"./toggle-icon.js";const ae=ae=>{var{type:se="checkbox",indicator:ne,checked:de,styleType:ce="default",children:me,childrenMaxLines:pe,subLabel:he,disabled:ue,error:be,name:ye,id:ve,className:fe,compositeSection:ge,removable:ke,focusableWhenDisabled:je,useContentWidth:xe,onRemove:Ne,onChange:$e,"data-testid":Ce,"aria-describedby":we}=ae,Le=e(ae,["type","indicator","checked","styleType","children","childrenMaxLines","subLabel","disabled","error","name","id","className","compositeSection","removable","focusableWhenDisabled","useContentWidth","onRemove","onChange","data-testid","aria-describedby"]);const{collapsible:Ae=!0,errors:De,children:Se,initialExpanded:Me}=ge||{},[We,Be]=s(de),[Re,Te]=s(!!Me),qe=n((()=>{const e=Array.isArray(De)&&(null==De?void 0:De.length)>0,i=!Array.isArray(De)&&!!De;return e||i}),[De]),Ee=y(),Ie=ve?`${ve}`:`tg-${Ee}`,_e=d(null),ze=d(null);u(ze,{[v.label.desktopLineClamp]:null==(null==pe?void 0:pe.desktop)?null:`${pe.desktop}`,[v.label.tabletLineClamp]:null==(null==pe?void 0:pe.tablet)?null:`${pe.tablet}`,[v.label.mobileLineClamp]:null==(null==pe?void 0:pe.mobile)?null:`${pe.mobile}`});const Fe=!!ue&&!!je,Oe=!!ue&&!je,Pe=!!ue;c((()=>{Be(de)}),[de]),c((()=>{We&&Te(null==Me||Me)}),[We]);const Ue=e=>{if(Pe)e.preventDefault();else if($e)$e(e);else switch(se){case"checkbox":Be((e=>!e));break;case"radio":case"yes":case"no":We||Be(!0)}},Ge=()=>{ue||Te(!Re)},He=()=>{ue||!Ne||Ne()},Je=()=>{var e;null===(e=null==_e?void 0:_e.current)||void 0===e||e.click()},Ke=e=>{e.stopPropagation()},Qe=()=>{let e;switch(se){case"yes":e="tick";break;case"no":e="cross";break;case"checkbox":case"radio":e=se}return r(oe,{type:e,active:We,disabled:ue,error:be})},Ve=()=>{if(!he)return null;let e;return e="function"==typeof he?he():he,r("div",{"data-id":"toggle-sublabel",id:`${Ie}-sublabel`,"aria-hidden":!0,className:H,children:e})},Xe=e=>{const l=a(J,ue&&V);return i(t,{children:[r(b.BodyMD,{weight:"semibold",className:l,children:"Error"}),r(h.Ul,{className:l,children:null==e?void 0:e.map(((e,i)=>r("li",{id:`${Ie}-error-list-item-${i}`,children:r(b.BodyMD,{weight:"semibold",className:l,children:e})},i)))})]})};return i("div",{className:a(f,!We&&be?W:"no-border"===ce?B:We&&ue?R:ue?T:be?W:We?q:E,We?be?I:ue?_:z:ue&&"no-border"!==ce?F:O,ue?null:We?be?P:U:G,!ne&&g,xe&&k,fe),id:ve,"data-testid":Ce,children:[(()=>{const e=["string"==typeof he?`${Ie}-sublabel`:null,we].filter(Boolean).join(" ")||void 0;return i("div",{id:`${Ie}-header-container`,className:j,children:[r("div",{className:a(D,ke&&S),children:i("div",{id:`${Ie}-input-container`,onClick:Je,className:x,children:[r("input",Object.assign({ref:_e,name:ye,id:`${Ie}-input`,type:"checkbox"===se?"checkbox":"radio","data-testid":"toggle-input",className:a(N,ue&&$),disabled:Oe,"aria-disabled":Fe,onChange:Ue,onClick:Ke,checked:We,tabIndex:Fe?0:void 0,"aria-describedby":e},Le)),ne&&Qe(),i("div",{className:a(A,We?be?J:ue?K:Q:ue?V:X),children:[r("label",{ref:ze,htmlFor:`${Ie}-input`,"data-testid":"toggle-label",id:`${Ie}-label`,className:a(C,We?w:L),children:me}),he&&Ve()]})]})}),ke&&r("button",{type:"button",className:a(M,ue&&$),onClick:He,id:`${Ie}-remove-button`,children:"Remove"})]})})(),Se&&i("div",{children:[(!Ae||Re)&&r("div",{"data-id":"toggle-composite-children",className:a(Y,!Ae&&Z,ue?V:X),children:r(p,{baseTextSize:"body-md",children:Se})}),Ae&&!Re&&qe&&r("div",{className:a(ie,ue?$:X),onClick:Ge,id:`${Ie}-error-alert`,children:r(m,{type:ue?"description":"error",className:ee,showIcon:!0,children:Array.isArray(De)?Xe(De):De})}),Ae&&r("button",{className:a(re,ue?$:te,!Re&&!qe&&le),disabled:ue,onClick:Ge,"data-testid":Re?"collapse-button":"expand-button",children:i(t,Re?{children:["Show less",r(o,{"aria-hidden":!0})]}:{children:["Show more",r(l,{"aria-hidden":!0})]})})]})]})};export{ae as Toggle};
2
2
  //# sourceMappingURL=toggle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toggle.js","sources":["../../src/toggle/toggle.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Alert } from \"../alert\";\nimport { Markup } from \"../markup\";\nimport { TextList } from \"../text-list\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./toggle.styles\";\nimport type { ToggleIconType } from \"./toggle-icon\";\nimport { ToggleIcon } from \"./toggle-icon\";\nimport type { ToggleProps } from \"./types\";\n\n// @catalog\n/**\n * A selectable control for checkbox and radio interaction patterns.\n *\n * Use `Toggle` to present a labeled option that the user can select or\n * deselect.\n */\nexport const Toggle = ({\n type = \"checkbox\",\n indicator,\n checked,\n styleType = \"default\",\n children,\n childrenMaxLines,\n subLabel,\n disabled,\n error,\n name,\n id,\n className,\n compositeSection,\n removable,\n focusableWhenDisabled,\n useContentWidth,\n onRemove,\n onChange,\n \"data-testid\": testId,\n \"aria-describedby\": ariaDescribedBy,\n ...otherProps\n}: ToggleProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n collapsible = true,\n errors,\n children: compositeSectionChildren,\n initialExpanded,\n } = compositeSection || {};\n const [selected, setSelected] = useState<boolean | undefined>(checked);\n const [expanded, setExpanded] = useState<boolean>(!!initialExpanded);\n const hasCompositeSectionError = useMemo(() => {\n const hasErrorList = Array.isArray(errors) && errors?.length > 0;\n const hasErrorElement = !Array.isArray(errors) && !!errors;\n return hasErrorList || hasErrorElement;\n }, [errors]);\n const uniqueId = useId();\n const generatedId = id ? `${id}` : `tg-${uniqueId}`;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const labelRef = useRef<HTMLLabelElement>(null);\n\n useApplyStyle(labelRef, {\n [styles.tokens.label.desktopLineClamp]:\n childrenMaxLines?.desktop == null\n ? null\n : `${childrenMaxLines.desktop}`,\n [styles.tokens.label.tabletLineClamp]:\n childrenMaxLines?.tablet == null\n ? null\n : `${childrenMaxLines.tablet}`,\n [styles.tokens.label.mobileLineClamp]:\n childrenMaxLines?.mobile == null\n ? null\n : `${childrenMaxLines.mobile}`,\n });\n\n const isFocusableWhenDisabled = !!disabled && !!focusableWhenDisabled;\n const isNativeDisabled = !!disabled && !focusableWhenDisabled;\n const isInteractionBlocked = !!disabled;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setSelected(checked);\n }, [checked]);\n\n useEffect(() => {\n if (selected) {\n setExpanded(initialExpanded ?? true);\n }\n }, [selected]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (isInteractionBlocked) {\n event.preventDefault();\n return;\n }\n\n if (onChange) {\n onChange(event);\n return;\n }\n\n switch (type) {\n case \"checkbox\":\n setSelected((prevSelected) => {\n return !prevSelected;\n });\n break;\n case \"radio\":\n case \"yes\":\n case \"no\":\n if (!selected) {\n setSelected(true);\n }\n break;\n }\n };\n\n const handleExpandCollapseClick = () => {\n if (!disabled) {\n setExpanded(!expanded);\n }\n };\n\n const handleOnRemove = () => {\n if (!disabled) {\n if (onRemove) {\n onRemove();\n return;\n }\n }\n };\n\n const handleContainerClick = () => {\n inputRef?.current?.click();\n };\n\n const handleInputClick = (e: React.MouseEvent<HTMLInputElement>) => {\n e.stopPropagation();\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const getContainerStateClass = () => {\n if (styleType === \"no-border\") {\n if (error) {\n return clsx(\n styles.colorBorderError,\n !disabled && styles.toggleContainerError\n );\n }\n\n if (disabled) {\n return selected\n ? styles.toggleContainerNoBorderDisabledSelected\n : styles.toggleContainerNoBorderDisabled;\n }\n\n if (selected) {\n return styles.toggleContainerNoBorderSelected;\n }\n\n return styles.toggleContainerNoBorder;\n }\n\n if (error) {\n return disabled\n ? styles.colorBorderError\n : styles.toggleContainerError;\n }\n\n if (disabled) {\n return selected\n ? styles.toggleContainerDisabledSelected\n : styles.toggleContainerDisabled;\n }\n\n if (selected) {\n return styles.toggleContainerSelected;\n }\n\n return styles.toggleContainer;\n };\n\n const getContainerHoverClass = () => {\n if (disabled) {\n return undefined;\n }\n\n if (!error && selected) {\n return styles.toggleContainerHoverSelected;\n }\n\n return styles.toggleContainerHoverDefault;\n };\n\n const getTextContainerStateClass = () => {\n if (disabled) {\n return selected\n ? styles.toggleTextContainerDisabledSelected\n : styles.colorTextDisabled;\n }\n\n if (selected) {\n return styles.toggleTextContainerSelected;\n }\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderIndicator = () => {\n let toggleIconType: ToggleIconType;\n\n switch (type) {\n case \"yes\":\n toggleIconType = \"tick\";\n break;\n case \"no\":\n toggleIconType = \"cross\";\n break;\n case \"checkbox\":\n case \"radio\":\n toggleIconType = type;\n break;\n }\n\n return (\n <ToggleIcon\n type={toggleIconType}\n active={selected}\n disabled={disabled}\n />\n );\n };\n\n const renderSubLabel = () => {\n if (!subLabel) {\n return null;\n }\n\n let component: string | JSX.Element;\n\n if (typeof subLabel === \"function\") {\n component = subLabel();\n } else {\n component = subLabel;\n }\n\n // Hide sublabel from screen readers as the main input already has aria-describedby that points to the sublabel\n return (\n <div\n data-id=\"toggle-sublabel\"\n id={`${generatedId}-sublabel`}\n aria-hidden\n className={styles.subLabel}\n >\n {component}\n </div>\n );\n };\n\n const renderCompositeChildren = () => {\n return (\n (!collapsible || expanded) && (\n <div\n data-id=\"toggle-composite-children\"\n className={clsx(\n styles.children,\n !collapsible && styles.childrenIsFinalItem,\n disabled && styles.colorTextDisabled\n )}\n >\n <Markup baseTextSize=\"body-md\">\n {compositeSectionChildren}\n </Markup>\n </div>\n )\n );\n };\n\n const renderExpandButton = () => {\n const collapsedWithoutErrors = !expanded && !hasCompositeSectionError;\n\n return (\n collapsible && (\n <button\n className={clsx(\n styles.expandButton,\n disabled && styles.disabledColorCursor,\n collapsedWithoutErrors &&\n styles.expandButtonPaddingTopRequired\n )}\n disabled={disabled}\n onClick={handleExpandCollapseClick}\n data-testid={expanded ? \"collapse-button\" : \"expand-button\"}\n >\n {expanded ? \"Show less\" : \"Show more\"}\n {expanded ? (\n <ChevronUpIcon aria-hidden />\n ) : (\n <ChevronDownIcon aria-hidden />\n )}\n </button>\n )\n );\n };\n\n const renderToggleWithRemoveButton = () => {\n const ariaDescriptions =\n [\n typeof subLabel === \"string\" ? `${generatedId}-sublabel` : null,\n ariaDescribedBy,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n return (\n <div\n id={`${generatedId}-header-container`}\n className={styles.headerContainer}\n >\n <div\n className={clsx(\n styles.indicatorLabelContainer,\n removable && styles.indicatorLabelContainerAddPadding\n )}\n >\n <div\n id={`${generatedId}-input-container`}\n onClick={handleContainerClick}\n className={styles.inputContainer}\n >\n <input\n ref={inputRef}\n name={name}\n id={`${generatedId}-input`}\n type={type === \"checkbox\" ? \"checkbox\" : \"radio\"}\n data-testid=\"toggle-input\"\n className={clsx(\n styles.input,\n disabled && styles.toggleInputDisabled\n )}\n disabled={isNativeDisabled}\n aria-disabled={isFocusableWhenDisabled}\n onChange={handleOnChange}\n onClick={handleInputClick}\n checked={selected}\n tabIndex={isFocusableWhenDisabled ? 0 : undefined}\n aria-describedby={ariaDescriptions}\n {...otherProps}\n />\n {indicator && renderIndicator()}\n <div\n className={clsx(\n styles.textContainer,\n getTextContainerStateClass()\n )}\n >\n <label\n ref={labelRef}\n htmlFor={`${generatedId}-input`}\n data-testid={`toggle-label`}\n id={`${generatedId}-label`}\n className={clsx(\n styles.label,\n selected\n ? styles.toggleLabelSelected\n : styles.toggleLabelDefault\n )}\n >\n {children}\n </label>\n {subLabel && renderSubLabel()}\n </div>\n </div>\n </div>\n {removable && (\n <button\n type=\"button\"\n className={clsx(\n styles.removeButton,\n disabled && styles.disabledColorCursor\n )}\n onClick={handleOnRemove}\n id={`${generatedId}-remove-button`}\n >\n Remove\n </button>\n )}\n </div>\n );\n };\n\n const renderErrorList = (errors: string[]) => {\n return (\n <>\n <Typography.BodyMD\n weight=\"semibold\"\n className={clsx(\n styles.colorTextError,\n disabled && styles.colorTextDisabled\n )}\n >\n Error\n </Typography.BodyMD>\n <TextList.Ul\n className={clsx(\n styles.colorTextError,\n disabled && styles.colorTextDisabled\n )}\n >\n {errors?.map((item, index) => {\n return (\n <li\n key={index}\n id={`${generatedId}-error-list-item-${index}`}\n >\n <Typography.BodyMD\n weight=\"semibold\"\n className={clsx(\n styles.colorTextError,\n disabled && styles.colorTextDisabled\n )}\n >\n {item}\n </Typography.BodyMD>\n </li>\n );\n })}\n </TextList.Ul>\n </>\n );\n };\n\n const renderError = () => {\n return (\n collapsible &&\n !expanded &&\n hasCompositeSectionError && (\n <div\n className={clsx(\n styles.errorContainer,\n disabled && styles.disabledColorCursor\n )}\n onClick={handleExpandCollapseClick}\n id={`${generatedId}-error-alert`}\n >\n <Alert\n type={disabled ? \"description\" : \"error\"}\n className={styles.alertContainer}\n showIcon\n >\n {Array.isArray(errors)\n ? renderErrorList(errors)\n : errors}\n </Alert>\n </div>\n )\n );\n };\n\n const renderCompositeSection = () => {\n return (\n compositeSectionChildren && (\n <div>\n {renderCompositeChildren()}\n {renderError()}\n {renderExpandButton()}\n </div>\n )\n );\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n getContainerStateClass(),\n getContainerHoverClass(),\n !indicator && styles.noIndicatorContainer,\n useContentWidth && styles.useContentWidthContainer,\n className\n )}\n id={id}\n data-testid={testId}\n >\n {renderToggleWithRemoveButton()}\n {renderCompositeSection()}\n </div>\n );\n};\n"],"names":["Toggle","_a","type","indicator","checked","styleType","children","childrenMaxLines","subLabel","disabled","error","name","id","className","compositeSection","removable","focusableWhenDisabled","useContentWidth","onRemove","onChange","testId","ariaDescribedBy","otherProps","__rest","collapsible","errors","compositeSectionChildren","initialExpanded","selected","setSelected","useState","expanded","setExpanded","hasCompositeSectionError","useMemo","hasErrorList","Array","isArray","length","hasErrorElement","uniqueId","useId","generatedId","inputRef","useRef","labelRef","useApplyStyle","styles.tokens","label","desktopLineClamp","desktop","tabletLineClamp","tablet","mobileLineClamp","mobile","isFocusableWhenDisabled","isNativeDisabled","isInteractionBlocked","useEffect","handleOnChange","event","preventDefault","prevSelected","handleExpandCollapseClick","handleOnRemove","handleContainerClick","current","click","handleInputClick","e","stopPropagation","renderIndicator","toggleIconType","_jsx","ToggleIcon","active","renderSubLabel","component","styles.subLabel","renderErrorList","_jsxs","_Fragment","Typography","BodyMD","weight","clsx","styles.colorTextError","styles.colorTextDisabled","TextList","Ul","map","item","index","styles.container","styles.colorBorderError","styles.toggleContainerError","styles.toggleContainerNoBorderDisabledSelected","styles.toggleContainerNoBorderDisabled","styles.toggleContainerNoBorderSelected","styles.toggleContainerNoBorder","styles.toggleContainerDisabledSelected","styles.toggleContainerDisabled","styles.toggleContainerSelected","styles.toggleContainer","styles.toggleContainerHoverSelected","styles.toggleContainerHoverDefault","getContainerHoverClass","styles.noIndicatorContainer","styles.useContentWidthContainer","ariaDescriptions","filter","Boolean","join","undefined","styles.headerContainer","styles.indicatorLabelContainer","styles.indicatorLabelContainerAddPadding","onClick","styles.inputContainer","ref","styles.input","styles.toggleInputDisabled","tabIndex","styles.textContainer","styles.toggleTextContainerDisabledSelected","styles.toggleTextContainerSelected","htmlFor","styles.label","styles.toggleLabelSelected","styles.toggleLabelDefault","styles.removeButton","styles.disabledColorCursor","renderToggleWithRemoveButton","styles.children","styles.childrenIsFinalItem","Markup","baseTextSize","styles.errorContainer","Alert","styles.alertContainer","showIcon","styles.expandButton","styles.expandButtonPaddingTopRequired","ChevronUpIcon","ChevronDownIcon"],"mappings":"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"}
1
+ {"version":3,"file":"toggle.js","sources":["../../src/toggle/toggle.tsx"],"sourcesContent":["import { ChevronDownIcon } from \"@lifesg/react-icons/chevron-down\";\nimport { ChevronUpIcon } from \"@lifesg/react-icons/chevron-up\";\nimport clsx from \"clsx\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Alert } from \"../alert\";\nimport { Markup } from \"../markup\";\nimport { TextList } from \"../text-list\";\nimport { useApplyStyle } from \"../theme\";\nimport { Typography } from \"../typography\";\nimport { useId } from \"../util\";\nimport * as styles from \"./toggle.styles\";\nimport type { ToggleIconType } from \"./toggle-icon\";\nimport { ToggleIcon } from \"./toggle-icon\";\nimport type { ToggleProps } from \"./types\";\n\n// @catalog\n/**\n * A selectable control for checkbox and radio interaction patterns.\n *\n * Use `Toggle` to present a labeled option that the user can select or\n * deselect.\n */\nexport const Toggle = ({\n type = \"checkbox\",\n indicator,\n checked,\n styleType = \"default\",\n children,\n childrenMaxLines,\n subLabel,\n disabled,\n error,\n name,\n id,\n className,\n compositeSection,\n removable,\n focusableWhenDisabled,\n useContentWidth,\n onRemove,\n onChange,\n \"data-testid\": testId,\n \"aria-describedby\": ariaDescribedBy,\n ...otherProps\n}: ToggleProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const {\n collapsible = true,\n errors,\n children: compositeSectionChildren,\n initialExpanded,\n } = compositeSection || {};\n const [selected, setSelected] = useState<boolean | undefined>(checked);\n const [expanded, setExpanded] = useState<boolean>(!!initialExpanded);\n const hasCompositeSectionError = useMemo(() => {\n const hasErrorList = Array.isArray(errors) && errors?.length > 0;\n const hasErrorElement = !Array.isArray(errors) && !!errors;\n return hasErrorList || hasErrorElement;\n }, [errors]);\n const uniqueId = useId();\n const generatedId = id ? `${id}` : `tg-${uniqueId}`;\n\n const inputRef = useRef<HTMLInputElement>(null);\n const labelRef = useRef<HTMLLabelElement>(null);\n\n useApplyStyle(labelRef, {\n [styles.tokens.label.desktopLineClamp]:\n childrenMaxLines?.desktop == null\n ? null\n : `${childrenMaxLines.desktop}`,\n [styles.tokens.label.tabletLineClamp]:\n childrenMaxLines?.tablet == null\n ? null\n : `${childrenMaxLines.tablet}`,\n [styles.tokens.label.mobileLineClamp]:\n childrenMaxLines?.mobile == null\n ? null\n : `${childrenMaxLines.mobile}`,\n });\n\n const isFocusableWhenDisabled = !!disabled && !!focusableWhenDisabled;\n const isNativeDisabled = !!disabled && !focusableWhenDisabled;\n const isInteractionBlocked = !!disabled;\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n setSelected(checked);\n }, [checked]);\n\n useEffect(() => {\n if (selected) {\n setExpanded(initialExpanded ?? true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [selected]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (isInteractionBlocked) {\n event.preventDefault();\n return;\n }\n\n if (onChange) {\n onChange(event);\n return;\n }\n\n switch (type) {\n case \"checkbox\":\n setSelected((prevSelected) => {\n return !prevSelected;\n });\n break;\n case \"radio\":\n case \"yes\":\n case \"no\":\n if (!selected) {\n setSelected(true);\n }\n break;\n }\n };\n\n const handleExpandCollapseClick = () => {\n if (!disabled) {\n setExpanded(!expanded);\n }\n };\n\n const handleOnRemove = () => {\n if (!disabled) {\n if (onRemove) {\n onRemove();\n return;\n }\n }\n };\n\n const handleContainerClick = () => {\n inputRef?.current?.click();\n };\n\n const handleInputClick = (e: React.MouseEvent<HTMLInputElement>) => {\n e.stopPropagation();\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n\n const getContainerBorderClass = () => {\n if (!selected && error) return styles.borderError;\n if (styleType === \"no-border\") return styles.borderNone;\n if (selected && disabled) return styles.borderSelectedDisabled;\n if (disabled) return styles.borderDisabled;\n if (error) return styles.borderError;\n if (selected) return styles.borderSelected;\n return styles.borderDefault;\n };\n\n const getContainerBgClass = () => {\n if (selected) {\n if (error) return styles.bgError;\n return disabled ? styles.bgSelectedDisabled : styles.bgSelected;\n }\n\n if (disabled && styleType !== \"no-border\") return styles.bgDisabled;\n return styles.bgDefault;\n };\n\n const getContainerHoverClass = () => {\n if (disabled) return null;\n if (selected)\n return error\n ? styles.toggleContainerHoverError\n : styles.toggleContainerHoverSelected;\n return styles.toggleContainerHoverDefault;\n };\n\n const getTextContainerClass = () => {\n if (selected) {\n if (error) return styles.colorTextError;\n\n if (disabled) return styles.toggleTextContainerDisabledSelected;\n\n return styles.toggleTextContainerSelected;\n }\n\n if (disabled) return styles.colorTextDisabled;\n return styles.colorTextDefault;\n };\n\n // =============================================================================\n // RENDER FUNCTIONS\n // =============================================================================\n const renderIndicator = () => {\n let toggleIconType: ToggleIconType;\n\n switch (type) {\n case \"yes\":\n toggleIconType = \"tick\";\n break;\n case \"no\":\n toggleIconType = \"cross\";\n break;\n case \"checkbox\":\n case \"radio\":\n toggleIconType = type;\n break;\n }\n\n return (\n <ToggleIcon\n type={toggleIconType}\n active={selected}\n disabled={disabled}\n error={error}\n />\n );\n };\n\n const renderSubLabel = () => {\n if (!subLabel) {\n return null;\n }\n\n let component: string | JSX.Element;\n\n if (typeof subLabel === \"function\") {\n component = subLabel();\n } else {\n component = subLabel;\n }\n\n // Hide sublabel from screen readers as the main input already has aria-describedby that points to the sublabel\n return (\n <div\n data-id=\"toggle-sublabel\"\n id={`${generatedId}-sublabel`}\n aria-hidden\n className={styles.subLabel}\n >\n {component}\n </div>\n );\n };\n\n const renderCompositeChildren = () => {\n return (\n (!collapsible || expanded) && (\n <div\n data-id=\"toggle-composite-children\"\n className={clsx(\n styles.children,\n !collapsible && styles.childrenIsFinalItem,\n disabled\n ? styles.colorTextDisabled\n : styles.colorTextDefault\n )}\n >\n <Markup baseTextSize=\"body-md\">\n {compositeSectionChildren}\n </Markup>\n </div>\n )\n );\n };\n\n const renderExpandButton = () => {\n const collapsedWithoutErrors = !expanded && !hasCompositeSectionError;\n\n return (\n collapsible && (\n <button\n className={clsx(\n styles.expandButton,\n disabled\n ? styles.disabledColorCursor\n : styles.colorTextPrimary,\n collapsedWithoutErrors &&\n styles.expandButtonPaddingTopRequired\n )}\n disabled={disabled}\n onClick={handleExpandCollapseClick}\n data-testid={expanded ? \"collapse-button\" : \"expand-button\"}\n >\n {expanded ? (\n <>\n Show less\n <ChevronUpIcon aria-hidden />\n </>\n ) : (\n <>\n Show more\n <ChevronDownIcon aria-hidden />\n </>\n )}\n </button>\n )\n );\n };\n\n const renderToggleWithRemoveButton = () => {\n const ariaDescriptions =\n [\n typeof subLabel === \"string\" ? `${generatedId}-sublabel` : null,\n ariaDescribedBy,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n\n return (\n <div\n id={`${generatedId}-header-container`}\n className={styles.headerContainer}\n >\n <div\n className={clsx(\n styles.indicatorLabelContainer,\n removable && styles.indicatorLabelContainerAddPadding\n )}\n >\n <div\n id={`${generatedId}-input-container`}\n onClick={handleContainerClick}\n className={styles.inputContainer}\n >\n <input\n ref={inputRef}\n name={name}\n id={`${generatedId}-input`}\n type={type === \"checkbox\" ? \"checkbox\" : \"radio\"}\n data-testid=\"toggle-input\"\n className={clsx(\n styles.input,\n disabled && styles.disabledColorCursor\n )}\n disabled={isNativeDisabled}\n aria-disabled={isFocusableWhenDisabled}\n onChange={handleOnChange}\n onClick={handleInputClick}\n checked={selected}\n tabIndex={isFocusableWhenDisabled ? 0 : undefined}\n aria-describedby={ariaDescriptions}\n {...otherProps}\n />\n {indicator && renderIndicator()}\n <div\n className={clsx(\n styles.textContainer,\n getTextContainerClass()\n )}\n >\n <label\n ref={labelRef}\n htmlFor={`${generatedId}-input`}\n data-testid={`toggle-label`}\n id={`${generatedId}-label`}\n className={clsx(\n styles.label,\n selected\n ? styles.toggleLabelSelected\n : styles.toggleLabelDefault\n )}\n >\n {children}\n </label>\n {subLabel && renderSubLabel()}\n </div>\n </div>\n </div>\n {removable && (\n <button\n type=\"button\"\n className={clsx(\n styles.removeButton,\n disabled && styles.disabledColorCursor\n )}\n onClick={handleOnRemove}\n id={`${generatedId}-remove-button`}\n >\n Remove\n </button>\n )}\n </div>\n );\n };\n\n const renderErrorList = (errors: string[]) => {\n const className = clsx(\n styles.colorTextError,\n disabled && styles.colorTextDisabled\n );\n\n return (\n <>\n <Typography.BodyMD weight=\"semibold\" className={className}>\n Error\n </Typography.BodyMD>\n <TextList.Ul className={className}>\n {errors?.map((item, index) => {\n return (\n <li\n key={index}\n id={`${generatedId}-error-list-item-${index}`}\n >\n <Typography.BodyMD\n weight=\"semibold\"\n className={className}\n >\n {item}\n </Typography.BodyMD>\n </li>\n );\n })}\n </TextList.Ul>\n </>\n );\n };\n\n const renderError = () => {\n return (\n collapsible &&\n !expanded &&\n hasCompositeSectionError && (\n <div\n className={clsx(\n styles.errorContainer,\n disabled\n ? styles.disabledColorCursor\n : styles.colorTextDefault\n )}\n onClick={handleExpandCollapseClick}\n id={`${generatedId}-error-alert`}\n >\n <Alert\n type={disabled ? \"description\" : \"error\"}\n className={styles.alertContainer}\n showIcon\n >\n {Array.isArray(errors)\n ? renderErrorList(errors)\n : errors}\n </Alert>\n </div>\n )\n );\n };\n\n const renderCompositeSection = () => {\n return (\n compositeSectionChildren && (\n <div>\n {renderCompositeChildren()}\n {renderError()}\n {renderExpandButton()}\n </div>\n )\n );\n };\n\n return (\n <div\n className={clsx(\n styles.container,\n getContainerBorderClass(),\n getContainerBgClass(),\n getContainerHoverClass(),\n !indicator && styles.containerNoIndicator,\n useContentWidth && styles.containerUseContentWidth,\n className\n )}\n id={id}\n data-testid={testId}\n >\n {renderToggleWithRemoveButton()}\n {renderCompositeSection()}\n </div>\n );\n};\n"],"names":["Toggle","_a","type","indicator","checked","styleType","children","childrenMaxLines","subLabel","disabled","error","name","id","className","compositeSection","removable","focusableWhenDisabled","useContentWidth","onRemove","onChange","testId","ariaDescribedBy","otherProps","__rest","collapsible","errors","compositeSectionChildren","initialExpanded","selected","setSelected","useState","expanded","setExpanded","hasCompositeSectionError","useMemo","hasErrorList","Array","isArray","length","hasErrorElement","uniqueId","useId","generatedId","inputRef","useRef","labelRef","useApplyStyle","styles.tokens","label","desktopLineClamp","desktop","tabletLineClamp","tablet","mobileLineClamp","mobile","isFocusableWhenDisabled","isNativeDisabled","isInteractionBlocked","useEffect","handleOnChange","event","preventDefault","prevSelected","handleExpandCollapseClick","handleOnRemove","handleContainerClick","current","click","handleInputClick","e","stopPropagation","renderIndicator","toggleIconType","_jsx","ToggleIcon","active","renderSubLabel","component","styles.subLabel","renderErrorList","clsx","styles.colorTextError","styles.colorTextDisabled","_jsxs","_Fragment","Typography","BodyMD","weight","TextList","Ul","map","item","index","styles.container","styles.borderError","styles.borderNone","styles.borderSelectedDisabled","styles.borderDisabled","styles.borderSelected","styles.borderDefault","styles.bgError","styles.bgSelectedDisabled","styles.bgSelected","styles.bgDisabled","styles.bgDefault","styles.toggleContainerHoverError","styles.toggleContainerHoverSelected","styles.toggleContainerHoverDefault","styles.containerNoIndicator","styles.containerUseContentWidth","ariaDescriptions","filter","Boolean","join","undefined","styles.headerContainer","styles.indicatorLabelContainer","styles.indicatorLabelContainerAddPadding","onClick","styles.inputContainer","ref","styles.input","styles.disabledColorCursor","tabIndex","styles.textContainer","styles.toggleTextContainerDisabledSelected","styles.toggleTextContainerSelected","styles.colorTextDefault","htmlFor","styles.label","styles.toggleLabelSelected","styles.toggleLabelDefault","styles.removeButton","renderToggleWithRemoveButton","styles.children","styles.childrenIsFinalItem","Markup","baseTextSize","styles.errorContainer","Alert","styles.alertContainer","showIcon","styles.expandButton","styles.colorTextPrimary","styles.expandButtonPaddingTopRequired","ChevronUpIcon","ChevronDownIcon"],"mappings":"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"}
@@ -5,27 +5,32 @@ export declare const tokens: {
5
5
  readonly mobileLineClamp: "--fds-internal-toggle-label-mobileLineClamp";
6
6
  };
7
7
  };
8
+ export declare const borderDefault: import("@linaria/core").LinariaClassName;
9
+ export declare const borderError: import("@linaria/core").LinariaClassName;
10
+ export declare const borderNone: import("@linaria/core").LinariaClassName;
11
+ export declare const borderSelected: import("@linaria/core").LinariaClassName;
12
+ export declare const borderDisabled: import("@linaria/core").LinariaClassName;
13
+ export declare const borderSelectedDisabled: import("@linaria/core").LinariaClassName;
14
+ export declare const bgDefault: import("@linaria/core").LinariaClassName;
15
+ export declare const bgSelected: import("@linaria/core").LinariaClassName;
16
+ export declare const bgError: import("@linaria/core").LinariaClassName;
17
+ export declare const bgDisabled: import("@linaria/core").LinariaClassName;
18
+ export declare const bgSelectedDisabled: import("@linaria/core").LinariaClassName;
19
+ export declare const colorTextDefault: import("@linaria/core").LinariaClassName;
20
+ export declare const colorTextPrimary: import("@linaria/core").LinariaClassName;
21
+ export declare const colorTextError: import("@linaria/core").LinariaClassName;
22
+ export declare const colorTextDisabled: import("@linaria/core").LinariaClassName;
8
23
  export declare const headerContainer: import("@linaria/core").LinariaClassName;
9
24
  export declare const textContainer: import("@linaria/core").LinariaClassName;
10
25
  export declare const toggleTextContainerSelected: import("@linaria/core").LinariaClassName;
11
26
  export declare const toggleTextContainerDisabledSelected: import("@linaria/core").LinariaClassName;
12
27
  export declare const container: import("@linaria/core").LinariaClassName;
13
- export declare const noIndicatorContainer: import("@linaria/core").LinariaClassName;
14
- export declare const useContentWidthContainer: import("@linaria/core").LinariaClassName;
15
- export declare const colorBorderError: import("@linaria/core").LinariaClassName;
16
- export declare const toggleContainerNoBorderDisabledSelected: import("@linaria/core").LinariaClassName;
17
- export declare const toggleContainerNoBorderDisabled: import("@linaria/core").LinariaClassName;
18
- export declare const toggleContainerNoBorderSelected: import("@linaria/core").LinariaClassName;
19
- export declare const toggleContainerNoBorder: import("@linaria/core").LinariaClassName;
20
- export declare const toggleContainerError: import("@linaria/core").LinariaClassName;
21
- export declare const toggleContainerDisabledSelected: import("@linaria/core").LinariaClassName;
22
- export declare const toggleContainerDisabled: import("@linaria/core").LinariaClassName;
23
- export declare const toggleContainerSelected: import("@linaria/core").LinariaClassName;
28
+ export declare const containerNoIndicator: import("@linaria/core").LinariaClassName;
29
+ export declare const containerUseContentWidth: import("@linaria/core").LinariaClassName;
30
+ export declare const toggleContainerHoverError: import("@linaria/core").LinariaClassName;
24
31
  export declare const toggleContainerHoverSelected: import("@linaria/core").LinariaClassName;
25
- export declare const toggleContainer: import("@linaria/core").LinariaClassName;
26
32
  export declare const toggleContainerHoverDefault: import("@linaria/core").LinariaClassName;
27
33
  export declare const input: import("@linaria/core").LinariaClassName;
28
- export declare const toggleInputDisabled: import("@linaria/core").LinariaClassName;
29
34
  export declare const inputContainer: import("@linaria/core").LinariaClassName;
30
35
  export declare const label: import("@linaria/core").LinariaClassName;
31
36
  export declare const toggleLabelDefault: import("@linaria/core").LinariaClassName;
@@ -40,6 +45,4 @@ export declare const expandButtonPaddingTopRequired: import("@linaria/core").Lin
40
45
  export declare const errorContainer: import("@linaria/core").LinariaClassName;
41
46
  export declare const children: import("@linaria/core").LinariaClassName;
42
47
  export declare const childrenIsFinalItem: import("@linaria/core").LinariaClassName;
43
- export declare const colorTextDisabled: import("@linaria/core").LinariaClassName;
44
- export declare const colorTextError: import("@linaria/core").LinariaClassName;
45
48
  export declare const alertContainer: import("@linaria/core").LinariaClassName;
@@ -1,2 +1,2 @@
1
- import"./toggle.styles_1t5qrye.css";const t={label:{desktopLineClamp:"--fds-internal-toggle-label-desktopLineClamp",tabletLineClamp:"--fds-internal-toggle-label-tabletLineClamp",mobileLineClamp:"--fds-internal-toggle-label-mobileLineClamp"}},e="h1fyul7s",l="tybgacj",i="tvkjim3",n="t1aku79x",s="c11szvws",a="n12ofp2c",o="u1l0nsei",g="c17z2k4k",c="tfiow01",p="td5xote",m="t15nuck4",r="tnwn55u",b="t1graj5g",w="t1qqpl3b",f="t1l2ct9g",y="t1tat3es",d="t1nsq3eo",k="t1cyflot",u="txm5wyu",C="i14lgw6r",q="tovnc4j",v="iangfw6",x="l1oixyvr",L="t1elmp69",j="tv1hw4w",h="s17sf3sp",z="i1l466bv",_="ih3od2r",A="r1izng22",G="d194isif",H="ehwglic",I="ejwzsce",M="e1q8ywpe",P="c1mf9nso",T="c9t56r4",B="c1y0x62l",D="c1gmwtb7",E="aeqryui";export{E as alertContainer,P as children,T as childrenIsFinalItem,g as colorBorderError,B as colorTextDisabled,D as colorTextError,s as container,G as disabledColorCursor,M as errorContainer,H as expandButton,I as expandButtonPaddingTopRequired,e as headerContainer,z as indicatorLabelContainer,_ as indicatorLabelContainerAddPadding,C as input,v as inputContainer,x as label,a as noIndicatorContainer,A as removeButton,h as subLabel,l as textContainer,k as toggleContainer,f as toggleContainerDisabled,w as toggleContainerDisabledSelected,b as toggleContainerError,u as toggleContainerHoverDefault,d as toggleContainerHoverSelected,r as toggleContainerNoBorder,p as toggleContainerNoBorderDisabled,c as toggleContainerNoBorderDisabledSelected,m as toggleContainerNoBorderSelected,y as toggleContainerSelected,q as toggleInputDisabled,L as toggleLabelDefault,j as toggleLabelSelected,n as toggleTextContainerDisabledSelected,i as toggleTextContainerSelected,t as tokens,o as useContentWidthContainer};
1
+ import"./toggle.styles_11tmfsr.css";const l={label:{desktopLineClamp:"--fds-internal-toggle-label-desktopLineClamp",tabletLineClamp:"--fds-internal-toggle-label-tabletLineClamp",mobileLineClamp:"--fds-internal-toggle-label-mobileLineClamp"}},e="b1fyul7s",t="bybgacj",i="bvkjim3",b="b1aku79x",s="b11szvws",a="b12ofp2c",n="b1l0nsei",o="b17z2k4k",c="bfiow01",g="bd5xote",m="b15nuck4",p="cnwn55u",r="c1graj5g",w="c1qqpl3b",f="c1l2ct9g",y="h1tat3es",d="t1nsq3eo",k="t1cyflot",C="txm5wyu",q="c14lgw6r",u="covnc4j",v="cangfw6",x="t1oixyvr",L="t1elmp69",j="tv1hw4w",z="i17sf3sp",h="i1l466bv",_="lh3od2r",A="t1izng22",G="t194isif",H="shwglic",I="ijwzsce",M="i1q8ywpe",P="r1mf9nso",T="d9t56r4",B="e1y0x62l",D="e1gmwtb7",E="eeqryui",F="cz4bsiy",J="c1k186w3",K="a15al1qe";export{K as alertContainer,n as bgDefault,g as bgDisabled,c as bgError,o as bgSelected,m as bgSelectedDisabled,e as borderDefault,s as borderDisabled,t as borderError,i as borderNone,b as borderSelected,a as borderSelectedDisabled,F as children,J as childrenIsFinalItem,p as colorTextDefault,f as colorTextDisabled,w as colorTextError,r as colorTextPrimary,q as container,u as containerNoIndicator,v as containerUseContentWidth,T as disabledColorCursor,E as errorContainer,B as expandButton,D as expandButtonPaddingTopRequired,y as headerContainer,I as indicatorLabelContainer,M as indicatorLabelContainerAddPadding,z as input,h as inputContainer,_ as label,P as removeButton,H as subLabel,d as textContainer,j as toggleContainerHoverDefault,x as toggleContainerHoverError,L as toggleContainerHoverSelected,A as toggleLabelDefault,G as toggleLabelSelected,C as toggleTextContainerDisabledSelected,k as toggleTextContainerSelected,l as tokens};
2
2
  //# sourceMappingURL=toggle.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toggle.styles.js","sources":["../../src/toggle/toggle.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Radius } from \"../theme\";\nimport * as toggleIconStyles from \"./toggle-icon.styles\";\n\nexport const tokens = {\n label: {\n desktopLineClamp: \"--fds-internal-toggle-label-desktopLineClamp\",\n tabletLineClamp: \"--fds-internal-toggle-label-tabletLineClamp\",\n mobileLineClamp: \"--fds-internal-toggle-label-mobileLineClamp\",\n },\n} as const;\n\n// =============================================================================\n// STYLING\n// =============================================================================\n\nexport const headerContainer = css`\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n`;\n\nexport const textContainer = css`\n display: flex;\n flex-direction: column;\n overflow-wrap: anywhere;\n width: 100%;\n overflow: hidden;\n color: ${Colour.text};\n`;\n\nexport const toggleTextContainerSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const toggleTextContainerDisabledSelected = css`\n color: ${Colour[\"text-selected-disabled\"]};\n`;\n\nexport const container = css`\n position: relative;\n display: inline-flex;\n min-width: 10.375rem;\n border-radius: ${Radius[\"sm\"]};\n border-width: 1px;\n border-style: solid;\n overflow: hidden;\n flex-direction: column;\n height: fit-content;\n background: ${Colour.bg};\n\n &:focus-within {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0;\n }\n`;\n\nexport const noIndicatorContainer = css`\n justify-content: center;\n`;\n\nexport const useContentWidthContainer = css`\n min-width: unset;\n`;\n\nexport const colorBorderError = css`\n border-color: ${Colour[\"border-error\"]};\n`;\n\nexport const toggleContainerNoBorderDisabledSelected = css`\n border: none;\n background: ${Colour[\"bg-selected-disabled\"]};\n`;\n\nexport const toggleContainerNoBorderDisabled = css`\n border: none;\n`;\n\nexport const toggleContainerNoBorderSelected = css`\n border: none;\n background: ${Colour[\"bg-selected\"]};\n`;\n\nexport const toggleContainerNoBorder = css`\n border: none;\n`;\n\nexport const toggleContainerError = css`\n border-color: ${Colour[\"border-error\"]};\n`;\n\nexport const toggleContainerDisabledSelected = css`\n border-color: ${Colour[\"border-selected-disabled\"]};\n background: ${Colour[\"bg-selected-disabled\"]};\n`;\n\nexport const toggleContainerDisabled = css`\n border-color: ${Colour[\"border-disabled\"]};\n background: ${Colour[\"bg-disabled\"]};\n`;\n\nexport const toggleContainerSelected = css`\n border-color: ${Colour[\"border-selected\"]};\n background: ${Colour[\"bg-selected\"]};\n`;\n\nexport const toggleContainerHoverSelected = css`\n &:has(.${headerContainer}:hover) {\n @media (pointer: fine) {\n background: ${Colour[\"bg-selected-hover\"]};\n\n & .${textContainer} {\n color: ${Colour[\"text-selected-hover\"]};\n }\n\n & .${toggleIconStyles.wrapperBase} {\n color: ${Colour[\"icon-selected-hover\"]};\n }\n }\n }\n`;\n\nexport const toggleContainer = css`\n border-color: ${Colour.border};\n`;\n\nexport const toggleContainerHoverDefault = css`\n &:has(.${headerContainer}:hover) {\n @media (pointer: fine) {\n background: ${Colour[\"bg-hover-subtle\"]};\n }\n }\n`;\n\nexport const input = css`\n position: absolute;\n height: 100%;\n width: 100%;\n cursor: pointer;\n top: 0;\n left: 0;\n opacity: 0;\n\n /* Hide appearance but keep it focusable using keyboard interactions */\n appearance: none;\n background: transparent;\n border: none;\n`;\n\nexport const toggleInputDisabled = css`\n cursor: not-allowed;\n`;\n\nexport const inputContainer = css`\n display: flex;\n`;\n\nexport const label = css`\n overflow: hidden;\n display: -webkit-box;\n text-overflow: ellipsis;\n -webkit-box-orient: vertical;\n overflow-wrap: break-word;\n\n ${tokens.label.desktopLineClamp}: initial;\n ${tokens.label.tabletLineClamp}: initial;\n ${tokens.label.mobileLineClamp}: initial;\n\n -webkit-line-clamp: var(${tokens.label.desktopLineClamp}, none);\n ${MediaQuery.MaxWidth.lg} {\n -webkit-line-clamp: var(${tokens.label.tabletLineClamp}, none);\n }\n ${MediaQuery.MaxWidth.sm} {\n -webkit-line-clamp: var(${tokens.label.mobileLineClamp}, none);\n }\n`;\n\nexport const toggleLabelDefault = css`\n ${Font[\"body-baseline-regular\"]}\n`;\n\nexport const toggleLabelSelected = css`\n ${Font[\"body-baseline-semibold\"]}\n`;\n\nexport const subLabel = css`\n ${Font[\"body-md-regular\"]}\n margin-top: 0.5rem;\n\n z-index: 1; // forces sublabel to render above the input\n pointer-events: none; // to allow click events to be passed to the input\n\n strong,\n b {\n ${Font[\"body-md-semibold\"]}\n }\n`;\n\nexport const indicatorLabelContainer = css`\n display: flex;\n height: 100%;\n width: 100%;\n position: relative;\n padding: 0.6875rem 1rem;\n`;\n\nexport const indicatorLabelContainerAddPadding = css`\n padding: 0.6875rem 0rem 0.6875rem 1rem;\n`;\n\nexport const removeButton = css`\n color: ${Colour[\"text-error\"]};\n white-space: nowrap;\n ${Font[\"body-md-semibold\"]}\n height: fit-content;\n padding: 0.6875rem 1rem 0.6875rem 0.5rem;\n border: none;\n background: none;\n cursor: pointer;\n`;\n\nexport const disabledColorCursor = css`\n color: ${Colour[\"text-disabled\"]};\n cursor: not-allowed;\n`;\n\nexport const expandButton = css`\n color: ${Colour[\"text-primary\"]};\n ${Font[\"body-baseline-semibold\"]}\n display: flex;\n align-items: center;\n justify-content: flex-end;\n border: none;\n background-color: ${Colour.bg};\n cursor: pointer;\n padding: 0 1rem 0.6875rem 1rem;\n width: 100%;\n\n svg {\n width: 1em;\n height: 1em;\n margin-left: 0.5rem;\n }\n`;\n\nexport const expandButtonPaddingTopRequired = css`\n padding-top: 0.6875rem;\n`;\n\nexport const errorContainer = css`\n width: 100%;\n color: ${Colour[\"text-error\"]};\n border: none;\n background: ${Colour.bg};\n cursor: pointer;\n padding: 0.6875rem 1rem 0.5rem 1rem;\n`;\n\nexport const children = css`\n padding: 0 1rem;\n padding-top: 0.6875rem;\n padding-bottom: 0.5rem;\n background-color: ${Colour.bg};\n color: ${Colour.text};\n`;\n\nexport const childrenIsFinalItem = css`\n padding-bottom: 0.6875rem;\n`;\n\nexport const colorTextDisabled = css`\n color: ${Colour[\"text-disabled\"]};\n`;\n\nexport const colorTextError = css`\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const alertContainer = css`\n width: 100%;\n user-select: none;\n`;\n"],"names":["tokens","label","desktopLineClamp","tabletLineClamp","mobileLineClamp","headerContainer","textContainer","toggleTextContainerSelected","toggleTextContainerDisabledSelected","container","noIndicatorContainer","useContentWidthContainer","colorBorderError","toggleContainerNoBorderDisabledSelected","toggleContainerNoBorderDisabled","toggleContainerNoBorderSelected","toggleContainerNoBorder","toggleContainerError","toggleContainerDisabledSelected","toggleContainerDisabled","toggleContainerSelected","toggleContainerHoverSelected","toggleContainer","toggleContainerHoverDefault","input","toggleInputDisabled","inputContainer","toggleLabelDefault","toggleLabelSelected","subLabel","indicatorLabelContainer","indicatorLabelContainerAddPadding","removeButton","disabledColorCursor","expandButton","expandButtonPaddingTopRequired","errorContainer","children","childrenIsFinalItem","colorTextDisabled","colorTextError","alertContainer"],"mappings":"0DAKO,MAAMA,EAAS,CAClBC,MAAO,CACHC,iBAAkB,+CAClBC,gBAAiB,8CACjBC,gBAAiB,gDAQZC,EAAe,WAMfC,EAAa,UASbC,EAA2B,UAI3BC,EAAmC,WAInCC,EAAS,WAkBTC,EAAoB,WAIpBC,EAAwB,WAIxBC,EAAgB,WAIhBC,EAAuC,UAKvCC,EAA+B,UAI/BC,EAA+B,WAK/BC,EAAuB,UAIvBC,EAAoB,WAIpBC,EAA+B,WAK/BC,EAAuB,WAKvBC,EAAuB,WAKvBC,EAA4B,WAgB5BC,EAAe,WAIfC,EAA2B,UAQ3BC,EAAK,WAeLC,EAAmB,UAInBC,EAAc,UAIdzB,EAAK,WAoBL0B,EAAkB,WAIlBC,EAAmB,UAInBC,EAAQ,WAaRC,EAAuB,WAQvBC,EAAiC,UAIjCC,EAAY,WAWZC,EAAmB,WAKnBC,EAAY,UAmBZC,EAA8B,UAI9BC,EAAc,WASdC,EAAQ,WAQRC,EAAmB,UAInBC,EAAiB,WAIjBC,EAAc,WAIdC,EAAc"}
1
+ {"version":3,"file":"toggle.styles.js","sources":["../../src/toggle/toggle.styles.ts"],"sourcesContent":["import { css } from \"@linaria/core\";\n\nimport { Colour, Font, MediaQuery, Radius } from \"../theme\";\nimport * as toggleIconStyles from \"./toggle-icon.styles\";\n\nexport const tokens = {\n label: {\n desktopLineClamp: \"--fds-internal-toggle-label-desktopLineClamp\",\n tabletLineClamp: \"--fds-internal-toggle-label-tabletLineClamp\",\n mobileLineClamp: \"--fds-internal-toggle-label-mobileLineClamp\",\n },\n} as const;\n\n// =============================================================================\n// BASIC STYLING\n// =============================================================================\n\nexport const borderDefault = css`\n border: solid 1px ${Colour.border};\n`;\n\nexport const borderError = css`\n border: solid 1px ${Colour[\"border-error\"]};\n`;\n\nexport const borderNone = css`\n border: solid 1px transparent;\n`;\n\nexport const borderSelected = css`\n border: solid 1px ${Colour[\"border-selected\"]};\n`;\n\nexport const borderDisabled = css`\n border: solid 1px ${Colour[\"border-disabled\"]};\n`;\n\nexport const borderSelectedDisabled = css`\n border: solid 1px ${Colour[\"border-selected-disabled\"]};\n`;\n\nexport const bgDefault = css`\n background: ${Colour.bg};\n`;\n\nexport const bgSelected = css`\n background: ${Colour[\"bg-selected\"]};\n`;\n\nexport const bgError = css`\n background: ${Colour[\"bg-error\"]};\n`;\n\nexport const bgDisabled = css`\n background: ${Colour[\"bg-disabled\"]};\n`;\n\nexport const bgSelectedDisabled = css`\n background: ${Colour[\"bg-selected-disabled\"]};\n`;\n\nexport const colorTextDefault = css`\n color: ${Colour.text};\n`;\n\nexport const colorTextPrimary = css`\n color: ${Colour[\"text-primary\"]};\n`;\n\nexport const colorTextError = css`\n color: ${Colour[\"text-error\"]};\n`;\n\nexport const colorTextDisabled = css`\n color: ${Colour[\"text-disabled\"]};\n`;\n\n// =============================================================================\n// STYLING\n// =============================================================================\n\nexport const headerContainer = css`\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n`;\n\nexport const textContainer = css`\n display: flex;\n flex-direction: column;\n overflow-wrap: anywhere;\n width: 100%;\n overflow: hidden;\n`;\n\nexport const toggleTextContainerSelected = css`\n color: ${Colour[\"text-selected\"]};\n`;\n\nexport const toggleTextContainerDisabledSelected = css`\n color: ${Colour[\"text-selected-disabled\"]};\n`;\n\nexport const container = css`\n position: relative;\n display: inline-flex;\n min-width: 10.375rem;\n border-radius: ${Radius[\"sm\"]};\n overflow: hidden;\n flex-direction: column;\n height: fit-content;\n\n &:focus-within {\n outline: 2px solid ${Colour[\"focus-ring\"]};\n outline-offset: 0;\n }\n\n &.${borderError}, &.${bgError} {\n &:focus-within {\n outline: 2px solid ${Colour[\"border-error-focus\"]};\n }\n }\n`;\n\nexport const containerNoIndicator = css`\n justify-content: center;\n`;\n\nexport const containerUseContentWidth = css`\n min-width: unset;\n`;\n\nexport const toggleContainerHoverError = css`\n &:has(.${headerContainer}:hover) {\n @media (pointer: fine) {\n background: ${Colour[\"bg-error-hover\"]};\n }\n }\n`;\n\nexport const toggleContainerHoverSelected = css`\n &:has(.${headerContainer}:hover) {\n @media (pointer: fine) {\n background: ${Colour[\"bg-selected-hover\"]};\n\n & .${textContainer} {\n color: ${Colour[\"text-selected-hover\"]};\n }\n\n & .${toggleIconStyles.wrapperBase} {\n color: ${Colour[\"icon-selected-hover\"]};\n }\n }\n }\n`;\n\nexport const toggleContainerHoverDefault = css`\n &:has(.${headerContainer}:hover) {\n @media (pointer: fine) {\n background: ${Colour[\"bg-hover-subtle\"]};\n }\n }\n`;\n\nexport const input = css`\n position: absolute;\n height: 100%;\n width: 100%;\n cursor: pointer;\n top: 0;\n left: 0;\n opacity: 0;\n\n /* Hide appearance but keep it focusable using keyboard interactions */\n appearance: none;\n background: transparent;\n border: none;\n`;\n\nexport const inputContainer = css`\n display: flex;\n`;\n\nexport const label = css`\n overflow: hidden;\n display: -webkit-box;\n text-overflow: ellipsis;\n -webkit-box-orient: vertical;\n overflow-wrap: break-word;\n\n ${tokens.label.desktopLineClamp}: initial;\n ${tokens.label.tabletLineClamp}: initial;\n ${tokens.label.mobileLineClamp}: initial;\n\n -webkit-line-clamp: var(${tokens.label.desktopLineClamp}, none);\n ${MediaQuery.MaxWidth.lg} {\n -webkit-line-clamp: var(${tokens.label.tabletLineClamp}, none);\n }\n ${MediaQuery.MaxWidth.sm} {\n -webkit-line-clamp: var(${tokens.label.mobileLineClamp}, none);\n }\n`;\n\nexport const toggleLabelDefault = css`\n ${Font[\"body-baseline-regular\"]}\n`;\n\nexport const toggleLabelSelected = css`\n ${Font[\"body-baseline-semibold\"]}\n`;\n\nexport const subLabel = css`\n ${Font[\"body-md-regular\"]}\n margin-top: 0.5rem;\n\n z-index: 1; // forces sublabel to render above the input\n pointer-events: none; // to allow click events to be passed to the input\n\n strong,\n b {\n ${Font[\"body-md-semibold\"]}\n }\n`;\n\nexport const indicatorLabelContainer = css`\n display: flex;\n height: 100%;\n width: 100%;\n position: relative;\n padding: 0.6875rem 1rem;\n`;\n\nexport const indicatorLabelContainerAddPadding = css`\n padding: 0.6875rem 0rem 0.6875rem 1rem;\n`;\n\nexport const removeButton = css`\n color: ${Colour[\"text-error\"]};\n white-space: nowrap;\n ${Font[\"body-md-semibold\"]}\n height: fit-content;\n padding: 0.6875rem 1rem 0.6875rem 0.5rem;\n border: none;\n background: none;\n cursor: pointer;\n`;\n\nexport const disabledColorCursor = css`\n color: ${Colour[\"text-disabled\"]};\n cursor: not-allowed;\n`;\n\nexport const expandButton = css`\n ${Font[\"body-baseline-semibold\"]}\n display: flex;\n align-items: center;\n justify-content: flex-end;\n border: none;\n background-color: ${Colour.bg};\n cursor: pointer;\n padding: 0 1rem 0.6875rem 1rem;\n width: 100%;\n\n svg {\n width: 1em;\n height: 1em;\n margin-left: 0.5rem;\n }\n`;\n\nexport const expandButtonPaddingTopRequired = css`\n padding-top: 0.6875rem;\n`;\n\nexport const errorContainer = css`\n width: 100%;\n border: none;\n background: ${Colour.bg};\n cursor: pointer;\n padding: 0.6875rem 1rem 0.5rem 1rem;\n`;\n\nexport const children = css`\n padding: 0 1rem;\n padding-top: 0.6875rem;\n padding-bottom: 0.5rem;\n background-color: ${Colour.bg};\n`;\n\nexport const childrenIsFinalItem = css`\n padding-bottom: 0.6875rem;\n`;\n\nexport const alertContainer = css`\n width: 100%;\n user-select: none;\n`;\n"],"names":["tokens","label","desktopLineClamp","tabletLineClamp","mobileLineClamp","borderDefault","borderError","borderNone","borderSelected","borderDisabled","borderSelectedDisabled","bgDefault","bgSelected","bgError","bgDisabled","bgSelectedDisabled","colorTextDefault","colorTextPrimary","colorTextError","colorTextDisabled","headerContainer","textContainer","toggleTextContainerSelected","toggleTextContainerDisabledSelected","container","containerNoIndicator","containerUseContentWidth","toggleContainerHoverError","toggleContainerHoverSelected","toggleContainerHoverDefault","input","inputContainer","toggleLabelDefault","toggleLabelSelected","subLabel","indicatorLabelContainer","indicatorLabelContainerAddPadding","removeButton","disabledColorCursor","expandButton","expandButtonPaddingTopRequired","errorContainer","children","childrenIsFinalItem","alertContainer"],"mappings":"0DAKO,MAAMA,EAAS,CAClBC,MAAO,CACHC,iBAAkB,+CAClBC,gBAAiB,8CACjBC,gBAAiB,gDAQZC,EAAa,WAIbC,EAAW,UAIXC,EAAU,UAIVC,EAAc,WAIdC,EAAc,WAIdC,EAAsB,WAItBC,EAAS,WAITC,EAAU,WAIVC,EAAO,UAIPC,EAAU,UAIVC,EAAkB,WAIlBC,EAAgB,UAIhBC,EAAgB,WAIhBC,EAAc,WAIdC,EAAiB,WAQjBC,EAAe,WAMfC,EAAa,WAQbC,EAA2B,WAI3BC,EAAmC,UAInCC,EAAS,WAqBTC,EAAoB,UAIpBC,EAAwB,UAIxBC,EAAyB,WAQzBC,EAA4B,WAgB5BC,EAA2B,UAQ3BC,EAAK,WAeLC,EAAc,WAId9B,EAAK,UAoBL+B,EAAkB,WAIlBC,EAAmB,WAInBC,EAAQ,UAaRC,EAAuB,UAQvBC,EAAiC,WAIjCC,EAAY,WAWZC,EAAmB,UAKnBC,EAAY,WAkBZC,EAA8B,WAI9BC,EAAc,UAQdC,EAAQ,UAORC,EAAmB,WAInBC,EAAc"}
@@ -0,0 +1,41 @@
1
+ @layer fds{.b1fyul7s{border:solid 1px var(--fds-colour-border);}
2
+ .bybgacj{border:solid 1px var(--fds-colour-border-error);}
3
+ .bvkjim3{border:solid 1px transparent;}
4
+ .b1aku79x{border:solid 1px var(--fds-colour-border-selected);}
5
+ .b11szvws{border:solid 1px var(--fds-colour-border-disabled);}
6
+ .b12ofp2c{border:solid 1px var(--fds-colour-border-selected-disabled);}
7
+ .b1l0nsei{background:var(--fds-colour-bg);}
8
+ .b17z2k4k{background:var(--fds-colour-bg-selected);}
9
+ .bfiow01{background:var(--fds-colour-bg-error);}
10
+ .bd5xote{background:var(--fds-colour-bg-disabled);}
11
+ .b15nuck4{background:var(--fds-colour-bg-selected-disabled);}
12
+ .cnwn55u{color:var(--fds-colour-text);}
13
+ .c1graj5g{color:var(--fds-colour-text-primary);}
14
+ .c1qqpl3b{color:var(--fds-colour-text-error);}
15
+ .c1l2ct9g{color:var(--fds-colour-text-disabled);}
16
+ .h1tat3es{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;-webkit-box-pack:justify;-ms-flex-pack:space-between;-webkit-justify-content:space-between;justify-content:space-between;}
17
+ .t1nsq3eo{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow-wrap:anywhere;width:100%;overflow:hidden;}
18
+ .t1cyflot{color:var(--fds-colour-text-selected);}
19
+ .txm5wyu{color:var(--fds-colour-text-selected-disabled);}
20
+ .c14lgw6r{position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;min-width:10.375rem;border-radius:var(--fds-radius-sm);overflow:hidden;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;}.c14lgw6r:focus-within{outline:2px solid var(--fds-colour-focus-ring);outline-offset:0;}.c14lgw6r.bybgacj:focus-within,.c14lgw6r.bfiow01:focus-within{outline:2px solid var(--fds-colour-border-error-focus);}
21
+ .covnc4j{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}
22
+ .cangfw6{min-width:unset;}
23
+ @media (pointer: fine){.t1oixyvr:has(.h1tat3es:hover){background:var(--fds-colour-bg-error-hover);}}
24
+ @media (pointer: fine){.t1elmp69:has(.h1tat3es:hover){background:var(--fds-colour-bg-selected-hover);}.t1elmp69:has(.h1tat3es:hover) .t1nsq3eo{color:var(--fds-colour-text-selected-hover);}.t1elmp69:has(.h1tat3es:hover) .wxufi5f{color:var(--fds-colour-icon-selected-hover);}}
25
+ @media (pointer: fine){.tv1hw4w:has(.h1tat3es:hover){background:var(--fds-colour-bg-hover-subtle);}}
26
+ .i17sf3sp{position:absolute;height:100%;width:100%;cursor:pointer;top:0;left:0;opacity:0;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none;background:transparent;border:none;}
27
+ .i1l466bv{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}
28
+ .lh3od2r{overflow:hidden;display:-webkit-box;text-overflow:ellipsis;-webkit-box-orient:vertical;overflow-wrap:break-word;--fds-internal-toggle-label-desktopLineClamp:initial;--fds-internal-toggle-label-tabletLineClamp:initial;--fds-internal-toggle-label-mobileLineClamp:initial;-webkit-line-clamp:var(--fds-internal-toggle-label-desktopLineClamp, none);}:where(body.fds-breakpoint-lg-max) .lh3od2r{-webkit-line-clamp:var(--fds-internal-toggle-label-tabletLineClamp, none);}:where(body.fds-breakpoint-sm-max) .lh3od2r{-webkit-line-clamp:var(--fds-internal-toggle-label-mobileLineClamp, none);}
29
+ .t1izng22{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-baseline);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-baseline);letter-spacing:var(--fds-font-body-ls-baseline);}
30
+ .t194isif{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-baseline);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-baseline);letter-spacing:var(--fds-font-body-ls-baseline);}
31
+ .shwglic{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-regular);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);margin-top:0.5rem;z-index:1;pointer-events:none;}.shwglic strong,.shwglic b{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);}
32
+ .ijwzsce{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;height:100%;width:100%;position:relative;padding:0.6875rem 1rem;}
33
+ .i1q8ywpe{padding:0.6875rem 0rem 0.6875rem 1rem;}
34
+ .r1mf9nso{color:var(--fds-colour-text-error);white-space:nowrap;font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-md);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-md);letter-spacing:var(--fds-font-body-ls-md);height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;padding:0.6875rem 1rem 0.6875rem 0.5rem;border:none;background:none;cursor:pointer;}
35
+ .d9t56r4{color:var(--fds-colour-text-disabled);cursor:not-allowed;}
36
+ .e1y0x62l{font-family:var(--fds-font-family-body);font-variant:var(--fds-font-variant);font-size:var(--fds-font-body-size-baseline);font-weight:var(--fds-font-weight-semibold);line-height:var(--fds-font-body-lh-baseline);letter-spacing:var(--fds-font-body-ls-baseline);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;border:none;background-color:var(--fds-colour-bg);cursor:pointer;padding:0 1rem 0.6875rem 1rem;width:100%;}.e1y0x62l svg{width:1em;height:1em;margin-left:0.5rem;}
37
+ .e1gmwtb7{padding-top:0.6875rem;}
38
+ .eeqryui{width:100%;border:none;background:var(--fds-colour-bg);cursor:pointer;padding:0.6875rem 1rem 0.5rem 1rem;}
39
+ .cz4bsiy{padding:0 1rem;padding-top:0.6875rem;padding-bottom:0.5rem;background-color:var(--fds-colour-bg);}
40
+ .c1k186w3{padding-bottom:0.6875rem;}
41
+ .a15al1qe{width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}}
@@ -1 +1 @@
1
- {"version":3,"file":"unit-number-input.js","sources":["../../src/unit-number/unit-number-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Input } from \"../input\";\nimport * as inputGroupStyles from \"../input-group/input-group.styles\";\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { InputWrapper } from \"../shared/input-wrapper\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId, useNextInputState } from \"../util\";\nimport type { UnitNumberInputProps } from \"./types\";\nimport * as styles from \"./unit-number-input.styles\";\n\ntype FieldType = \"floor\" | \"unit\" | \"none\";\ntype ValueFieldTypes = Exclude<FieldType, \"none\">;\n\n// @catalog\n/**\n * A two-field input for entering Singapore-style unit numbers in `floor-unit` format.\n *\n * Use `UnitNumberInput` when you need a structured unit number entry that splits\n * floor and unit into separate fields.\n */\nexport const UnitNumberInput = ({\n disabled,\n error,\n value,\n onChange,\n onBlur,\n onChangeRaw,\n onBlurRaw,\n readOnly,\n placeholder = \"00-8888\",\n autoComplete,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": ariaInvalid,\n className,\n ...otherProps\n}: UnitNumberInputProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [floorValue, _setFloorValue] = useState<string>(\"\");\n const [unitValue, _setUnitValue] = useState<string>(\"\");\n const [currentFocus, _setCurrentFocus] = useState<FieldType>(\"none\");\n const internalId = useId();\n const floorLabelId = `${internalId}-floor-label`;\n const unitLabelId = `${internalId}-unit-label`;\n const liveMessageId = `${internalId}-live-message`;\n\n const nodeRef = useRef<HTMLDivElement>(null);\n const floorInputRef = useRef<HTMLInputElement>(null);\n const unitInputRef = useRef<HTMLInputElement>(null);\n\n /**\n * Have to use refs to allow the state values to be accessible\n * by the event listener callback functions\n * Reference:\n * https://stackoverflow.com/questions/55265255/react-usestate-hook-event-handler-using-initial-state\n */\n\n const floorValueStateRef = useRef<string>(floorValue);\n const unitValueStateRef = useRef<string>(unitValue);\n const currentFocusStateRef = useRef<FieldType>(currentFocus);\n\n const formatter = (value: string) =>\n value.toLocaleUpperCase().replace(/[^0-9A-Za-z]/g, \"\");\n const getNextFloorInputState = useNextInputState({\n ref: floorInputRef,\n formatter,\n });\n const getNextUnitInputState = useNextInputState({\n ref: unitInputRef,\n formatter,\n });\n\n const liveMessage = useMemo(() => {\n let msg = \"\";\n const floorMsg = formatPhraseWithPrefix(\"Hash\", floorValue);\n const unitMsg = formatPhraseWithPrefix(\"Dash\", unitValue);\n switch (currentFocus) {\n case \"floor\":\n msg = floorMsg;\n break;\n case \"unit\":\n msg = floorValue ? [floorMsg, unitMsg].join(\" \") : unitMsg;\n break;\n default:\n msg = \"\";\n }\n return msg;\n }, [currentFocus, floorValue, unitValue]);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setFloorValue = (data: string) => {\n floorValueStateRef.current = data;\n _setFloorValue(data);\n };\n\n const setUnitValue = (data: string) => {\n unitValueStateRef.current = data;\n _setUnitValue(data);\n };\n\n const setCurrentFocus = (data: FieldType) => {\n currentFocusStateRef.current = data;\n _setCurrentFocus(data);\n };\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n // Auto focus feature\n if (\n currentFocus === \"floor\" &&\n floorValue.length === 3 &&\n unitInputRef.current\n ) {\n unitInputRef.current.focus();\n }\n }, [floorValue]);\n\n useEffect(() => {\n updateValues(value);\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n setCurrentFocus(event.target.name as FieldType);\n event.target.select();\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const targetName = event.target.name as FieldType;\n const targetValue = event.target.value;\n const formattedInput = formatInput(targetValue);\n\n if (targetName === \"floor\") {\n setFloorValue(formattedInput);\n if (formattedInput !== floorValue) {\n performOnChangeHandler(formattedInput, targetName);\n }\n } else if (targetName === \"unit\") {\n setUnitValue(formattedInput);\n if (formattedInput !== unitValue) {\n performOnChangeHandler(formattedInput, targetName);\n }\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const targetName = event.target.name as FieldType;\n\n if (targetName === \"floor\") {\n const nextInputState = getNextFloorInputState();\n if (!nextInputState) return;\n\n const { nextValue, updateCaretPosition } = nextInputState;\n updateCaretPosition();\n setFloorValue(nextValue);\n performOnChangeHandler(nextValue, targetName);\n } else if (targetName === \"unit\") {\n const nextInputState = getNextUnitInputState();\n if (!nextInputState) return;\n\n const { nextValue, updateCaretPosition } = nextInputState;\n updateCaretPosition();\n setUnitValue(nextValue);\n performOnChangeHandler(nextValue, targetName);\n }\n };\n\n const handleNodeClick = () => {\n if (currentFocus === \"none\" && floorInputRef.current) {\n floorInputRef.current.focus();\n }\n };\n\n const handleNodeBlur = (event: React.FocusEvent) => {\n if (nodeRef.current && nodeRef.current.contains(event.relatedTarget)) {\n // internal element received focus\n return;\n }\n if (currentFocusStateRef.current !== \"none\") {\n setCurrentFocus(\"none\");\n performOnBlurHandler();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n /**\n * Allow going to the field before if user presses Backspace\n * on an empty field\n */\n if (event.code === \"Backspace\" || event.key === \"Backspace\") {\n if (currentFocus === \"unit\" && unitValue.length === 0) {\n floorInputRef.current?.focus();\n }\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const formatInput = (value: string) => {\n return /^[0-9]$/.test(value)\n ? StringHelper.padValue(value, true)\n : value.toLocaleUpperCase();\n };\n\n const updateValues = (value: string | undefined) => {\n if (value === INVALID_VALUE) {\n return;\n } else if (value === undefined || value.length === 0) {\n setFloorValue(\"\");\n setUnitValue(\"\");\n } else {\n const valueArr = value.split(\"-\");\n if (valueArr.length === 2) {\n // Valid value\n const floor = valueArr[0];\n const unit = valueArr[1];\n setFloorValue(\n currentFocus === \"floor\" ? floor : formatInput(floor)\n );\n setUnitValue(\n currentFocus === \"unit\" ? unit : formatInput(unit)\n );\n }\n }\n };\n\n const performOnChangeHandler = (\n changeValue: string,\n field: ValueFieldTypes\n ) => {\n if (!onChange && !onChangeRaw) {\n return;\n }\n\n const values: Record<ValueFieldTypes, string> = {\n floor: floorValueStateRef.current,\n unit: unitValueStateRef.current,\n };\n\n // Update the specific field value\n values[field] = changeValue;\n\n if (onChange) {\n const returnValue = getFormattedValue(values);\n onChange(returnValue);\n }\n\n if (onChangeRaw) {\n onChangeRaw([values.floor, values.unit]);\n }\n };\n\n const performOnBlurHandler = () => {\n if (!onBlur && !onBlurRaw) {\n return;\n }\n\n const values: Record<ValueFieldTypes, string> = {\n floor: formatInput(floorValueStateRef.current),\n unit: formatInput(unitValueStateRef.current),\n };\n\n if (onBlur) {\n const returnValue = getFormattedValue(values);\n onBlur(returnValue);\n }\n\n if (onBlurRaw) {\n onBlurRaw([values.floor, values.unit]);\n }\n };\n\n const getFormattedValue = (values: Record<ValueFieldTypes, string>) => {\n const valueArr = [values.floor, values.unit];\n\n if (values.floor.length > 0 && values.unit.length > 0) {\n return valueArr.join(\"-\");\n } else if (valueArr.every((value) => value === \"\")) {\n return \"\";\n } else {\n return INVALID_VALUE;\n }\n };\n\n const getPlaceholder = (value: string) => {\n return value.split(\"-\");\n };\n\n function formatPhraseWithPrefix(prefix: string, v: string) {\n return v ? `${prefix} ${Array.from(v).join(\" \")}` : \"\";\n }\n\n // =============================================================================\n // RENDER FUNCTION\n // =============================================================================\n const renderInputs = () => (\n <>\n <Input\n name=\"floor\"\n maxLength={3}\n value={floorValue}\n ref={floorInputRef}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n disabled={disabled}\n readOnly={readOnly}\n type=\"text\"\n pattern=\"[0-9A-Z]{2,3}\"\n data-testid=\"floor-input\"\n aria-labelledby={concatIds(ariaLabelledBy, floorLabelId)}\n aria-describedby={concatIds(ariaDescribedBy, liveMessageId)}\n aria-invalid={ariaInvalid}\n placeholder={\n currentFocus === \"floor\" && !readOnly && !disabled\n ? \"\"\n : getPlaceholder(placeholder)[0]\n }\n autoComplete={autoComplete}\n styleType=\"no-border\"\n className={clsx(styles.input, styles.floorInput)}\n />\n <VisuallyHidden aria-hidden id={floorLabelId}>\n Enter floor number\n </VisuallyHidden>\n <Typography.BodyBL\n className={clsx(\n styles.unitNumberDivider,\n floorValue.length === 0 && styles.unitNumberDividerInactive\n )}\n >\n -\n </Typography.BodyBL>\n <Input\n name=\"unit\"\n maxLength={5}\n value={unitValue}\n ref={unitInputRef}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n type=\"text\"\n pattern=\"[0-9A-Z]{2,5}\"\n data-testid=\"unit-input\"\n aria-labelledby={concatIds(ariaLabelledBy, unitLabelId)}\n aria-describedby={concatIds(ariaDescribedBy, liveMessageId)}\n aria-invalid={ariaInvalid}\n placeholder={\n currentFocus === \"unit\" && !readOnly && !disabled\n ? \"\"\n : getPlaceholder(placeholder)[1]\n }\n autoComplete={autoComplete}\n styleType=\"no-border\"\n className={clsx(\n styles.input,\n styles.floorInput,\n styles.unitInput\n )}\n />\n <VisuallyHidden aria-hidden id={unitLabelId}>\n Enter unit number\n </VisuallyHidden>\n {/** Live message for AT reader to read with the combination of prefix and current value for both floor input and unit input */}\n <VisuallyHidden id={liveMessageId} aria-live=\"polite\">\n {liveMessage}\n </VisuallyHidden>\n </>\n );\n\n const renderReadOnly = (displayValue: string) => {\n const displayValueArr = displayValue.split(\"-\");\n const liveMessageForReadOnly = [\n formatPhraseWithPrefix(\"Hash\", displayValueArr[0]),\n formatPhraseWithPrefix(\"Dash\", displayValueArr[1]),\n ].join(\" \");\n\n return (\n <div\n data-testid=\"readonly-display\"\n tabIndex={0}\n role=\"textbox\"\n aria-readonly\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n className={styles.readOnlyContainer}\n >\n <Typography.BodyBL>{displayValueArr[0]}</Typography.BodyBL>\n <Typography.BodyBL className={styles.unitNumberDivider}>\n -\n </Typography.BodyBL>\n <Typography.BodyBL>{displayValueArr[1]}</Typography.BodyBL>\n <VisuallyHidden>{liveMessageForReadOnly}</VisuallyHidden>\n </div>\n );\n };\n\n return (\n <InputWrapper\n {...otherProps}\n ref={nodeRef}\n onClick={handleNodeClick}\n disabled={disabled}\n error={error}\n readOnly={readOnly}\n tabIndex={-1}\n onBlur={handleNodeBlur}\n className={className}\n >\n <div\n data-testid=\"addon\"\n className={clsx(\n styles.hashContainer,\n inputGroupStyles.labelAddonContainer\n )}\n data-disabled={disabled}\n data-read-only={readOnly}\n >\n #\n </div>\n {readOnly && value ? renderReadOnly(value) : renderInputs()}\n </InputWrapper>\n );\n};\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst INVALID_VALUE = \"Invalid unit number\";\n"],"names":["UnitNumberInput","_a","disabled","error","value","onChange","onBlur","onChangeRaw","onBlurRaw","readOnly","placeholder","autoComplete","ariaLabelledBy","ariaDescribedBy","ariaInvalid","className","otherProps","__rest","floorValue","_setFloorValue","useState","unitValue","_setUnitValue","currentFocus","_setCurrentFocus","internalId","useId","floorLabelId","unitLabelId","liveMessageId","nodeRef","useRef","floorInputRef","unitInputRef","floorValueStateRef","unitValueStateRef","currentFocusStateRef","formatter","toLocaleUpperCase","replace","getNextFloorInputState","useNextInputState","ref","getNextUnitInputState","liveMessage","useMemo","msg","floorMsg","formatPhraseWithPrefix","unitMsg","join","setFloorValue","data","current","setUnitValue","setCurrentFocus","useEffect","length","focus","updateValues","handleFocus","event","target","name","select","handleBlur","targetName","targetValue","formattedInput","formatInput","performOnChangeHandler","handleChange","nextInputState","nextValue","updateCaretPosition","handleKeyDown","code","key","test","StringHelper","padValue","INVALID_VALUE","undefined","valueArr","split","floor","unit","changeValue","field","values","returnValue","getFormattedValue","performOnBlurHandler","every","getPlaceholder","prefix","v","Array","from","_jsxs","InputWrapper","Object","assign","onClick","tabIndex","contains","relatedTarget","children","_jsx","clsx","styles.hashContainer","inputGroupStyles.labelAddonContainer","displayValue","displayValueArr","liveMessageForReadOnly","role","styles.readOnlyContainer","Typography","BodyBL","styles.unitNumberDivider","VisuallyHidden","renderReadOnly","_Fragment","Input","maxLength","onFocus","type","pattern","concatIds","styleType","styles.input","styles.floorInput","id","styles.unitNumberDividerInactive","onKeyDown","styles.unitInput"],"mappings":"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"}
1
+ {"version":3,"file":"unit-number-input.js","sources":["../../src/unit-number/unit-number-input.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport type React from \"react\";\nimport { useEffect, useMemo, useRef, useState } from \"react\";\n\nimport { Input } from \"../input\";\nimport * as inputGroupStyles from \"../input-group/input-group.styles\";\nimport { concatIds, VisuallyHidden } from \"../shared/accessibility\";\nimport { InputWrapper } from \"../shared/input-wrapper\";\nimport { Typography } from \"../typography\";\nimport { StringHelper, useId, useNextInputState } from \"../util\";\nimport type { UnitNumberInputProps } from \"./types\";\nimport * as styles from \"./unit-number-input.styles\";\n\ntype FieldType = \"floor\" | \"unit\" | \"none\";\ntype ValueFieldTypes = Exclude<FieldType, \"none\">;\n\n// @catalog\n/**\n * A two-field input for entering Singapore-style unit numbers in `floor-unit` format.\n *\n * Use `UnitNumberInput` when you need a structured unit number entry that splits\n * floor and unit into separate fields.\n */\nexport const UnitNumberInput = ({\n disabled,\n error,\n value,\n onChange,\n onBlur,\n onChangeRaw,\n onBlurRaw,\n readOnly,\n placeholder = \"00-8888\",\n autoComplete,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-describedby\": ariaDescribedBy,\n \"aria-invalid\": ariaInvalid,\n className,\n ...otherProps\n}: UnitNumberInputProps) => {\n // =============================================================================\n // CONST, STATE, REF\n // =============================================================================\n const [floorValue, _setFloorValue] = useState<string>(\"\");\n const [unitValue, _setUnitValue] = useState<string>(\"\");\n const [currentFocus, _setCurrentFocus] = useState<FieldType>(\"none\");\n const internalId = useId();\n const floorLabelId = `${internalId}-floor-label`;\n const unitLabelId = `${internalId}-unit-label`;\n const liveMessageId = `${internalId}-live-message`;\n\n const nodeRef = useRef<HTMLDivElement>(null);\n const floorInputRef = useRef<HTMLInputElement>(null);\n const unitInputRef = useRef<HTMLInputElement>(null);\n\n /**\n * Have to use refs to allow the state values to be accessible\n * by the event listener callback functions\n * Reference:\n * https://stackoverflow.com/questions/55265255/react-usestate-hook-event-handler-using-initial-state\n */\n\n const floorValueStateRef = useRef<string>(floorValue);\n const unitValueStateRef = useRef<string>(unitValue);\n const currentFocusStateRef = useRef<FieldType>(currentFocus);\n\n const formatter = (value: string) =>\n value.toLocaleUpperCase().replace(/[^0-9A-Za-z]/g, \"\");\n const getNextFloorInputState = useNextInputState({\n ref: floorInputRef,\n formatter,\n });\n const getNextUnitInputState = useNextInputState({\n ref: unitInputRef,\n formatter,\n });\n\n const liveMessage = useMemo(() => {\n let msg = \"\";\n const floorMsg = formatPhraseWithPrefix(\"Hash\", floorValue);\n const unitMsg = formatPhraseWithPrefix(\"Dash\", unitValue);\n switch (currentFocus) {\n case \"floor\":\n msg = floorMsg;\n break;\n case \"unit\":\n msg = floorValue ? [floorMsg, unitMsg].join(\" \") : unitMsg;\n break;\n default:\n msg = \"\";\n }\n return msg;\n }, [currentFocus, floorValue, unitValue]);\n\n // =============================================================================\n // REF FUNCTIONS\n // =============================================================================\n const setFloorValue = (data: string) => {\n floorValueStateRef.current = data;\n _setFloorValue(data);\n };\n\n const setUnitValue = (data: string) => {\n unitValueStateRef.current = data;\n _setUnitValue(data);\n };\n\n const setCurrentFocus = (data: FieldType) => {\n currentFocusStateRef.current = data;\n _setCurrentFocus(data);\n };\n\n // =============================================================================\n // EFFECTS\n // =============================================================================\n useEffect(() => {\n // Auto focus feature\n if (\n currentFocus === \"floor\" &&\n floorValue.length === 3 &&\n unitInputRef.current\n ) {\n unitInputRef.current.focus();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [floorValue]);\n\n useEffect(() => {\n updateValues(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n // =============================================================================\n // EVENT HANDLERS\n // =============================================================================\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n setCurrentFocus(event.target.name as FieldType);\n event.target.select();\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n const targetName = event.target.name as FieldType;\n const targetValue = event.target.value;\n const formattedInput = formatInput(targetValue);\n\n if (targetName === \"floor\") {\n setFloorValue(formattedInput);\n if (formattedInput !== floorValue) {\n performOnChangeHandler(formattedInput, targetName);\n }\n } else if (targetName === \"unit\") {\n setUnitValue(formattedInput);\n if (formattedInput !== unitValue) {\n performOnChangeHandler(formattedInput, targetName);\n }\n }\n };\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const targetName = event.target.name as FieldType;\n\n if (targetName === \"floor\") {\n const nextInputState = getNextFloorInputState();\n if (!nextInputState) return;\n\n const { nextValue, updateCaretPosition } = nextInputState;\n updateCaretPosition();\n setFloorValue(nextValue);\n performOnChangeHandler(nextValue, targetName);\n } else if (targetName === \"unit\") {\n const nextInputState = getNextUnitInputState();\n if (!nextInputState) return;\n\n const { nextValue, updateCaretPosition } = nextInputState;\n updateCaretPosition();\n setUnitValue(nextValue);\n performOnChangeHandler(nextValue, targetName);\n }\n };\n\n const handleNodeClick = () => {\n if (currentFocus === \"none\" && floorInputRef.current) {\n floorInputRef.current.focus();\n }\n };\n\n const handleNodeBlur = (event: React.FocusEvent) => {\n if (nodeRef.current && nodeRef.current.contains(event.relatedTarget)) {\n // internal element received focus\n return;\n }\n if (currentFocusStateRef.current !== \"none\") {\n setCurrentFocus(\"none\");\n performOnBlurHandler();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n /**\n * Allow going to the field before if user presses Backspace\n * on an empty field\n */\n if (event.code === \"Backspace\" || event.key === \"Backspace\") {\n if (currentFocus === \"unit\" && unitValue.length === 0) {\n floorInputRef.current?.focus();\n }\n }\n };\n\n // =============================================================================\n // HELPER FUNCTIONS\n // =============================================================================\n const formatInput = (value: string) => {\n return /^[0-9]$/.test(value)\n ? StringHelper.padValue(value, true)\n : value.toLocaleUpperCase();\n };\n\n const updateValues = (value: string | undefined) => {\n if (value === INVALID_VALUE) {\n return;\n } else if (value === undefined || value.length === 0) {\n setFloorValue(\"\");\n setUnitValue(\"\");\n } else {\n const valueArr = value.split(\"-\");\n if (valueArr.length === 2) {\n // Valid value\n const floor = valueArr[0];\n const unit = valueArr[1];\n setFloorValue(\n currentFocus === \"floor\" ? floor : formatInput(floor)\n );\n setUnitValue(\n currentFocus === \"unit\" ? unit : formatInput(unit)\n );\n }\n }\n };\n\n const performOnChangeHandler = (\n changeValue: string,\n field: ValueFieldTypes\n ) => {\n if (!onChange && !onChangeRaw) {\n return;\n }\n\n const values: Record<ValueFieldTypes, string> = {\n floor: floorValueStateRef.current,\n unit: unitValueStateRef.current,\n };\n\n // Update the specific field value\n values[field] = changeValue;\n\n if (onChange) {\n const returnValue = getFormattedValue(values);\n onChange(returnValue);\n }\n\n if (onChangeRaw) {\n onChangeRaw([values.floor, values.unit]);\n }\n };\n\n const performOnBlurHandler = () => {\n if (!onBlur && !onBlurRaw) {\n return;\n }\n\n const values: Record<ValueFieldTypes, string> = {\n floor: formatInput(floorValueStateRef.current),\n unit: formatInput(unitValueStateRef.current),\n };\n\n if (onBlur) {\n const returnValue = getFormattedValue(values);\n onBlur(returnValue);\n }\n\n if (onBlurRaw) {\n onBlurRaw([values.floor, values.unit]);\n }\n };\n\n const getFormattedValue = (values: Record<ValueFieldTypes, string>) => {\n const valueArr = [values.floor, values.unit];\n\n if (values.floor.length > 0 && values.unit.length > 0) {\n return valueArr.join(\"-\");\n } else if (valueArr.every((value) => value === \"\")) {\n return \"\";\n } else {\n return INVALID_VALUE;\n }\n };\n\n const getPlaceholder = (value: string) => {\n return value.split(\"-\");\n };\n\n function formatPhraseWithPrefix(prefix: string, v: string) {\n return v ? `${prefix} ${Array.from(v).join(\" \")}` : \"\";\n }\n\n // =============================================================================\n // RENDER FUNCTION\n // =============================================================================\n const renderInputs = () => (\n <>\n <Input\n name=\"floor\"\n maxLength={3}\n value={floorValue}\n ref={floorInputRef}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n disabled={disabled}\n readOnly={readOnly}\n type=\"text\"\n pattern=\"[0-9A-Z]{2,3}\"\n data-testid=\"floor-input\"\n aria-labelledby={concatIds(ariaLabelledBy, floorLabelId)}\n aria-describedby={concatIds(ariaDescribedBy, liveMessageId)}\n aria-invalid={ariaInvalid}\n placeholder={\n currentFocus === \"floor\" && !readOnly && !disabled\n ? \"\"\n : getPlaceholder(placeholder)[0]\n }\n autoComplete={autoComplete}\n styleType=\"no-border\"\n className={clsx(styles.input, styles.floorInput)}\n />\n <VisuallyHidden aria-hidden id={floorLabelId}>\n Enter floor number\n </VisuallyHidden>\n <Typography.BodyBL\n className={clsx(\n styles.unitNumberDivider,\n floorValue.length === 0 && styles.unitNumberDividerInactive\n )}\n >\n -\n </Typography.BodyBL>\n <Input\n name=\"unit\"\n maxLength={5}\n value={unitValue}\n ref={unitInputRef}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n readOnly={readOnly}\n type=\"text\"\n pattern=\"[0-9A-Z]{2,5}\"\n data-testid=\"unit-input\"\n aria-labelledby={concatIds(ariaLabelledBy, unitLabelId)}\n aria-describedby={concatIds(ariaDescribedBy, liveMessageId)}\n aria-invalid={ariaInvalid}\n placeholder={\n currentFocus === \"unit\" && !readOnly && !disabled\n ? \"\"\n : getPlaceholder(placeholder)[1]\n }\n autoComplete={autoComplete}\n styleType=\"no-border\"\n className={clsx(\n styles.input,\n styles.floorInput,\n styles.unitInput\n )}\n />\n <VisuallyHidden aria-hidden id={unitLabelId}>\n Enter unit number\n </VisuallyHidden>\n {/** Live message for AT reader to read with the combination of prefix and current value for both floor input and unit input */}\n <VisuallyHidden id={liveMessageId} aria-live=\"polite\">\n {liveMessage}\n </VisuallyHidden>\n </>\n );\n\n const renderReadOnly = (displayValue: string) => {\n const displayValueArr = displayValue.split(\"-\");\n const liveMessageForReadOnly = [\n formatPhraseWithPrefix(\"Hash\", displayValueArr[0]),\n formatPhraseWithPrefix(\"Dash\", displayValueArr[1]),\n ].join(\" \");\n\n return (\n <div\n data-testid=\"readonly-display\"\n tabIndex={0}\n role=\"textbox\"\n aria-readonly\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n aria-invalid={ariaInvalid}\n className={styles.readOnlyContainer}\n >\n <Typography.BodyBL>{displayValueArr[0]}</Typography.BodyBL>\n <Typography.BodyBL className={styles.unitNumberDivider}>\n -\n </Typography.BodyBL>\n <Typography.BodyBL>{displayValueArr[1]}</Typography.BodyBL>\n <VisuallyHidden>{liveMessageForReadOnly}</VisuallyHidden>\n </div>\n );\n };\n\n return (\n <InputWrapper\n {...otherProps}\n ref={nodeRef}\n onClick={handleNodeClick}\n disabled={disabled}\n error={error}\n readOnly={readOnly}\n tabIndex={-1}\n onBlur={handleNodeBlur}\n className={className}\n >\n <div\n data-testid=\"addon\"\n className={clsx(\n styles.hashContainer,\n inputGroupStyles.labelAddonContainer\n )}\n data-disabled={disabled}\n data-read-only={readOnly}\n >\n #\n </div>\n {readOnly && value ? renderReadOnly(value) : renderInputs()}\n </InputWrapper>\n );\n};\n\n// =============================================================================\n// CONSTANTS\n// =============================================================================\nconst INVALID_VALUE = \"Invalid unit number\";\n"],"names":["UnitNumberInput","_a","disabled","error","value","onChange","onBlur","onChangeRaw","onBlurRaw","readOnly","placeholder","autoComplete","ariaLabelledBy","ariaDescribedBy","ariaInvalid","className","otherProps","__rest","floorValue","_setFloorValue","useState","unitValue","_setUnitValue","currentFocus","_setCurrentFocus","internalId","useId","floorLabelId","unitLabelId","liveMessageId","nodeRef","useRef","floorInputRef","unitInputRef","floorValueStateRef","unitValueStateRef","currentFocusStateRef","formatter","toLocaleUpperCase","replace","getNextFloorInputState","useNextInputState","ref","getNextUnitInputState","liveMessage","useMemo","msg","floorMsg","formatPhraseWithPrefix","unitMsg","join","setFloorValue","data","current","setUnitValue","setCurrentFocus","useEffect","length","focus","updateValues","handleFocus","event","target","name","select","handleBlur","targetName","targetValue","formattedInput","formatInput","performOnChangeHandler","handleChange","nextInputState","nextValue","updateCaretPosition","handleKeyDown","code","key","test","StringHelper","padValue","INVALID_VALUE","undefined","valueArr","split","floor","unit","changeValue","field","values","returnValue","getFormattedValue","performOnBlurHandler","every","getPlaceholder","prefix","v","Array","from","_jsxs","InputWrapper","Object","assign","onClick","tabIndex","contains","relatedTarget","children","_jsx","clsx","styles.hashContainer","inputGroupStyles.labelAddonContainer","displayValue","displayValueArr","liveMessageForReadOnly","role","styles.readOnlyContainer","Typography","BodyBL","styles.unitNumberDivider","VisuallyHidden","renderReadOnly","_Fragment","Input","maxLength","onFocus","type","pattern","concatIds","styleType","styles.input","styles.floorInput","id","styles.unitNumberDividerInactive","onKeyDown","styles.unitInput"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"is-styled-components.js","sources":["../../src/util/is-styled-components.ts"],"sourcesContent":["/*\n Extracted isStyledComponent function from styled-components repo \n Refer to the original implementation here:\n https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/utils/isStyledComponent.ts\n*/\n\ntype StyledComponentBrand = { readonly _sc: symbol };\n\nexport default function isStyledComponent(\n target: any\n): target is StyledComponentBrand {\n return (\n target != null &&\n (typeof target === \"function\" || typeof target === \"object\") &&\n \"styledComponentId\" in target\n );\n}\n"],"names":["isStyledComponent","target"],"mappings":"AAQc,SAAUA,EACpBC,GAEA,OACc,MAAVA,IACmB,mBAAXA,GAA2C,iBAAXA,IACxC,sBAAuBA,CAE/B"}
1
+ {"version":3,"file":"is-styled-components.js","sources":["../../src/util/is-styled-components.ts"],"sourcesContent":["/*\n Extracted isStyledComponent function from styled-components repo \n Refer to the original implementation here:\n https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/utils/isStyledComponent.ts\n*/\n\ntype StyledComponentBrand = { readonly _sc: symbol };\n\nexport default function isStyledComponent(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n target: any\n): target is StyledComponentBrand {\n return (\n target != null &&\n (typeof target === \"function\" || typeof target === \"object\") &&\n \"styledComponentId\" in target\n );\n}\n"],"names":["isStyledComponent","target"],"mappings":"AAQc,SAAUA,EAEpBC,GAEA,OACc,MAAVA,IACmB,mBAAXA,GAA2C,iBAAXA,IACxC,sBAAuBA,CAE/B"}
@@ -46,8 +46,8 @@ export declare class StringHelper {
46
46
  static getTextWidth(text: string, font: string): number;
47
47
  static maskValue(value: string, options: MaskValueOptions): string;
48
48
  private static determineStartAndEndIndex;
49
- private static ordinalPluralRules;
50
- private static suffixes;
49
+ private static readonly ordinalPluralRules;
50
+ private static readonly suffixes;
51
51
  static formatOrdinal(n: number): string;
52
52
  static getMaskedDescription(value: string, displayMaskState: "masked" | "unmasked", maskRange?: number[]): string;
53
53
  static joinNonEmptyStrings(strings: (string | undefined | null)[], delimiter?: string): string;
@@ -1,2 +1,2 @@
1
- class t{static transformWithSpaces(t,e){const n="(.{"+e+"})";return t.replace(/[^\dA-Z]/gi,"").replace(new RegExp(n,"g"),"$1 ").trim()}static padValue(t,e){if("0"===t)return e?t:t.padStart(2,"0");if(""===t)return t;return parseInt(t).toString().padStart(2,"0")}static shouldTruncateToTwoLines(t,e){const n=Math.floor(e/9);return t.length>=2*n||1===t.split(" ").length&&t.length>n}static truncateOneLine(t,e,n,r,s=8){let a=0;e>n&&(a=Math.floor((e-n)/s));const i=r+a;if(i<t.length){const e=Math.floor(i/2);return t.substring(0,e)+" ... "+t.substring(t.length-e,t.length)}return t}static truncateTwoLines(t,e,n,r=1.2){const s=Math.floor(2*e/(.6*n))*(2/r);if(t.length<=s)return t;const a=Math.floor(.6*s),i=Math.floor(.2*s);return`${t.substring(0,a)}...${t.substring(t.length-i)}`}static getTextWidth(e,n){if("undefined"==typeof document)return 0;const r=(t.getTextWidth.canvas||(t.getTextWidth.canvas=document.createElement("canvas"))).getContext("2d");r.font=n;return r.measureText(e).width}static maskValue(e,n){if(!e)return e;const{maskRange:r,unmaskRange:s,maskChar:a="•",maskRegex:i,maskTransformer:u}=n;if(u)return u(e);if(i)return e.replace(i,a);if(r){const{startIndex:n,endIndex:s}=t.determineStartAndEndIndex(r[0],r[1]);return e.substring(0,n)+a.repeat(e.substring(n,s+1).length)+e.substring(s+1)}if(s){const{startIndex:n,endIndex:r}=t.determineStartAndEndIndex(s[0],s[1]);return a.repeat(e.substring(0,n).length)+e.substring(n,r+1)+a.repeat(e.substring(r+1).length)}return e}static determineStartAndEndIndex(t,e){return t<e?{startIndex:t,endIndex:e}:{startIndex:e,endIndex:t}}static formatOrdinal(e){const n=t.ordinalPluralRules.select(e);return`${e}${t.suffixes.get(n)}`}static getMaskedDescription(t,e,n){if(!t||"masked"!==e||!n)return"";const[r,s]=n,a=r>0,i=s<t.length-1,u=a?t.substring(0,r):"",o=i?t.substring(s+1):"";return a&&i?`Starting with ${u} and ending with ${o}`:a?`Starting with ${u}`:i?`Ending with ${o}`:""}static joinNonEmptyStrings(t,e=", "){return t.filter(Boolean).join(e)}}t.ordinalPluralRules=new Intl.PluralRules("en",{type:"ordinal"}),t.suffixes=new Map([["one","st"],["two","nd"],["few","rd"],["other","th"]]);export{t as StringHelper};
1
+ class t{static transformWithSpaces(t,e){const n="(.{"+e+"})";return t.replace(/[^\dA-Z]/gi,"").replace(new RegExp(n,"g"),"$1 ").trim()}static padValue(t,e){if("0"===t)return e?t:t.padStart(2,"0");if(""===t)return t;return parseInt(t).toString().padStart(2,"0")}static shouldTruncateToTwoLines(t,e){const n=Math.floor(e/9);return t.length>=2*n||1===t.split(" ").length&&t.length>n}static truncateOneLine(t,e,n,r,s=8){let a=0;e>n&&(a=Math.floor((e-n)/s));const i=r+a;if(i<t.length){const e=Math.floor(i/2);return t.substring(0,e)+" ... "+t.substring(t.length-e,t.length)}return t}static truncateTwoLines(t,e,n,r=1.2){const s=Math.floor(2*e/(.6*n))*(2/r);if(t.length<=s)return t;const a=Math.floor(.6*s),i=Math.floor(.2*s);return`${t.substring(0,a)}...${t.substring(t.length-i)}`}static getTextWidth(t,e){if("undefined"==typeof document)return 0;const n=(this.getTextWidth.canvas||(this.getTextWidth.canvas=document.createElement("canvas"))).getContext("2d");n.font=e;return n.measureText(t).width}static maskValue(t,e){if(!t)return t;const{maskRange:n,unmaskRange:r,maskChar:s="•",maskRegex:a,maskTransformer:i}=e;if(i)return i(t);if(a)return t.replace(a,s);if(n){const{startIndex:e,endIndex:r}=this.determineStartAndEndIndex(n[0],n[1]);return t.substring(0,e)+s.repeat(t.substring(e,r+1).length)+t.substring(r+1)}if(r){const{startIndex:e,endIndex:n}=this.determineStartAndEndIndex(r[0],r[1]);return s.repeat(t.substring(0,e).length)+t.substring(e,n+1)+s.repeat(t.substring(n+1).length)}return t}static determineStartAndEndIndex(t,e){return t<e?{startIndex:t,endIndex:e}:{startIndex:e,endIndex:t}}static formatOrdinal(t){const e=this.ordinalPluralRules.select(t);return`${t}${this.suffixes.get(e)}`}static getMaskedDescription(t,e,n){if(!t||"masked"!==e||!n)return"";const[r,s]=n,a=r>0,i=s<t.length-1,u=a?t.substring(0,r):"",o=i?t.substring(s+1):"";return a&&i?`Starting with ${u} and ending with ${o}`:a?`Starting with ${u}`:i?`Ending with ${o}`:""}static joinNonEmptyStrings(t,e=", "){return t.filter(Boolean).join(e)}}t.ordinalPluralRules=new Intl.PluralRules("en",{type:"ordinal"}),t.suffixes=new Map([["one","st"],["two","nd"],["few","rd"],["other","th"]]);export{t as StringHelper};
2
2
  //# sourceMappingURL=string-helper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"string-helper.js","sources":["../../src/util/string-helper.ts"],"sourcesContent":["// =============================================================================\n// TYPINGS\n// =============================================================================\ninterface MaskValueOptions {\n maskRange?: number[] | undefined;\n unmaskRange?: number[] | undefined;\n maskRegex?: RegExp | undefined;\n maskTransformer?: ((value: string) => string) | undefined;\n maskChar?: string | undefined;\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\nexport class StringHelper {\n public static transformWithSpaces(\n value: string | any,\n groupLength: number\n ): string {\n const regex = \"(.{\" + groupLength + \"})\";\n return value\n .replace(/[^\\dA-Z]/gi, \"\")\n .replace(new RegExp(regex, \"g\"), \"$1 \")\n .trim();\n }\n\n /**\n * Pads single digit values with a zero and trims leading zero for\n * values of length more than 2\n * @param value the string value\n * @param retainSingleZero setting true will allow single zero value\n */\n public static padValue(value: string, retainSingleZero?: boolean): string {\n if (value === \"0\") {\n return retainSingleZero ? value : value.padStart(2, \"0\");\n }\n\n if (value === \"\") {\n return value;\n }\n\n const trimmedValue = parseInt(value);\n return trimmedValue.toString().padStart(2, \"0\");\n }\n\n /**\n * Checks if the text is required to be truncated and broken into two lines based\n * on the available width of container. **Note: This is relevant to font size 18px or 1.125rem only **\n * @param text input text\n * @param widthOfElement element width in px\n */\n public static shouldTruncateToTwoLines(\n text: string,\n widthOfElement: number\n ): boolean {\n // This is arbitrary and based on tests to derive that every 9px increment ~= 1 char length.\n // But this applies to font size 18px or 1.125rem only\n const estimatedCharOnLine = Math.floor(widthOfElement / 9);\n return (\n text.length >= estimatedCharOnLine * 2 ||\n (text.split(\" \").length === 1 && text.length > estimatedCharOnLine)\n );\n }\n\n /**\n * Performs a truncation by adding ellipsis in the middle of the text.\n * @param text input text\n * @param widthOfElement the dynamic width of the container in px\n * @param minDivSize the minimum container size (using size on mobileS viewport as baseline)\n * @param baselineCharLength the baseline amount of characters to be displayed before truncation kicks. This\n * will be increased if there is more space available (derived from `widthOfElement`)\n * @param incrementFactor the size (in px).\n */\n public static truncateOneLine(\n text: string,\n widthOfElement: number,\n minDivSize: number,\n baselineCharLength: number,\n incrementFactor = 8 // Arbitrary based on tests and applies to font size of 18px or 1.125rem\n ): string {\n let additionalCharAllowed = 0;\n if (widthOfElement > minDivSize) {\n additionalCharAllowed = Math.floor(\n (widthOfElement - minDivSize) / incrementFactor\n );\n }\n const allowedCharLength = baselineCharLength + additionalCharAllowed;\n if (allowedCharLength < text.length) {\n const thresholdIndex = Math.floor(allowedCharLength / 2); // We will cut it halfway to derive x num of characters\n return (\n text.substring(0, thresholdIndex) + // Use the first x\n \" ... \" +\n text.substring(text.length - thresholdIndex, text.length) // Use the last x\n );\n }\n\n return text;\n }\n\n /**\n * Performs a truncation by adding ellipsis in the middle of the text.\n * @param text input text\n * @param widthOfElement the dynamic width of the container in px\n * @param fontSize the fontsize of the text\n * @param lineHeight the line height of the text\n */\n public static truncateTwoLines(\n text: string,\n widthOfElement: number,\n fontSize: number,\n lineHeight = 1.2\n ): string {\n // Estimate characters per line based on width and font size\n const charsPerLine = Math.floor(\n (widthOfElement * 2) / (fontSize * 0.6) // 0.6 is an approximation for average char width\n );\n\n // Calculate total characters allowed in two lines\n const totalCharsAllowed = charsPerLine * (2 / lineHeight);\n\n if (text.length <= totalCharsAllowed) {\n return text; // No truncation needed\n }\n\n // Calculate the number of characters to keep\n const keepFromStart = Math.floor(totalCharsAllowed * 0.6); // Keep 60% from start\n const keepFromEnd = Math.floor(totalCharsAllowed * 0.2); // Keep 20% from end\n\n // Truncate the text\n const start = text.substring(0, keepFromStart);\n const end = text.substring(text.length - keepFromEnd);\n\n return `${start}...${end}`;\n }\n\n /**\n * Returns the width of the text in the specified font\n * https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\n */\n public static getTextWidth(text: string, font: string): number {\n if (typeof document === \"undefined\") {\n return 0;\n }\n\n // create a reusable canvas object for better performance\n const canvas =\n (StringHelper.getTextWidth as any).canvas ||\n ((StringHelper.getTextWidth as any).canvas =\n document.createElement(\"canvas\"));\n const context = canvas.getContext(\"2d\");\n context.font = font;\n\n const metrics = context.measureText(text);\n return metrics.width;\n }\n\n public static maskValue(value: string, options: MaskValueOptions): string {\n if (!value) {\n return value;\n }\n\n const {\n maskRange,\n unmaskRange,\n maskChar = \"•\",\n maskRegex,\n maskTransformer,\n } = options;\n\n if (maskTransformer) {\n return maskTransformer(value);\n } else if (maskRegex) {\n return value.replace(maskRegex, maskChar);\n } else if (maskRange) {\n const { startIndex, endIndex } =\n StringHelper.determineStartAndEndIndex(\n maskRange[0],\n maskRange[1]\n );\n return (\n value.substring(0, startIndex) +\n maskChar.repeat(\n value.substring(startIndex, endIndex + 1).length\n ) +\n value.substring(endIndex + 1)\n );\n } else if (unmaskRange) {\n const { startIndex, endIndex } =\n StringHelper.determineStartAndEndIndex(\n unmaskRange[0],\n unmaskRange[1]\n );\n return (\n maskChar.repeat(value.substring(0, startIndex).length) +\n value.substring(startIndex, endIndex + 1) +\n maskChar.repeat(value.substring(endIndex + 1).length)\n );\n }\n\n return value;\n }\n\n private static determineStartAndEndIndex(index0: number, index1: number) {\n return index0 < index1\n ? { startIndex: index0, endIndex: index1 }\n : { startIndex: index1, endIndex: index0 };\n }\n\n private static ordinalPluralRules = new Intl.PluralRules(\"en\", {\n type: \"ordinal\",\n });\n\n private static suffixes = new Map([\n [\"one\", \"st\"],\n [\"two\", \"nd\"],\n [\"few\", \"rd\"],\n [\"other\", \"th\"],\n ]);\n\n public static formatOrdinal(n: number) {\n const rule = StringHelper.ordinalPluralRules.select(n);\n const suffix = StringHelper.suffixes.get(rule);\n return `${n}${suffix}`;\n }\n\n public static getMaskedDescription(\n value: string,\n displayMaskState: \"masked\" | \"unmasked\",\n maskRange?: number[]\n ): string {\n if (!value || displayMaskState !== \"masked\" || !maskRange) return \"\";\n\n const [startIndex, endIndex] = maskRange;\n const hasStart = startIndex > 0;\n const hasEnd = endIndex < value.length - 1;\n\n const start = hasStart ? value.substring(0, startIndex) : \"\";\n const end = hasEnd ? value.substring(endIndex + 1) : \"\";\n\n if (hasStart && hasEnd)\n return `Starting with ${start} and ending with ${end}`;\n if (hasStart) return `Starting with ${start}`;\n if (hasEnd) return `Ending with ${end}`;\n\n return \"\";\n }\n\n public static joinNonEmptyStrings(\n strings: (string | undefined | null)[],\n delimiter = \", \"\n ): string {\n return strings.filter(Boolean).join(delimiter);\n }\n}\n"],"names":["StringHelper","transformWithSpaces","value","groupLength","regex","replace","RegExp","trim","padValue","retainSingleZero","padStart","parseInt","toString","shouldTruncateToTwoLines","text","widthOfElement","estimatedCharOnLine","Math","floor","length","split","truncateOneLine","minDivSize","baselineCharLength","incrementFactor","additionalCharAllowed","allowedCharLength","thresholdIndex","substring","truncateTwoLines","fontSize","lineHeight","totalCharsAllowed","keepFromStart","keepFromEnd","getTextWidth","font","document","context","canvas","createElement","getContext","measureText","width","maskValue","options","maskRange","unmaskRange","maskChar","maskRegex","maskTransformer","startIndex","endIndex","determineStartAndEndIndex","repeat","index0","index1","formatOrdinal","n","rule","ordinalPluralRules","select","suffixes","get","getMaskedDescription","displayMaskState","hasStart","hasEnd","start","end","joinNonEmptyStrings","strings","delimiter","filter","Boolean","join","Intl","PluralRules","type","Map"],"mappings":"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"}
1
+ {"version":3,"file":"string-helper.js","sources":["../../src/util/string-helper.ts"],"sourcesContent":["// =============================================================================\n// TYPINGS\n// =============================================================================\ninterface MaskValueOptions {\n maskRange?: number[] | undefined;\n unmaskRange?: number[] | undefined;\n maskRegex?: RegExp | undefined;\n maskTransformer?: ((value: string) => string) | undefined;\n maskChar?: string | undefined;\n}\n\n// =============================================================================\n// EXPORTS\n// =============================================================================\nexport class StringHelper {\n public static transformWithSpaces(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: string | any,\n groupLength: number\n ): string {\n const regex = \"(.{\" + groupLength + \"})\";\n return value\n .replace(/[^\\dA-Z]/gi, \"\")\n .replace(new RegExp(regex, \"g\"), \"$1 \")\n .trim();\n }\n\n /**\n * Pads single digit values with a zero and trims leading zero for\n * values of length more than 2\n * @param value the string value\n * @param retainSingleZero setting true will allow single zero value\n */\n public static padValue(value: string, retainSingleZero?: boolean): string {\n if (value === \"0\") {\n return retainSingleZero ? value : value.padStart(2, \"0\");\n }\n\n if (value === \"\") {\n return value;\n }\n\n const trimmedValue = parseInt(value);\n return trimmedValue.toString().padStart(2, \"0\");\n }\n\n /**\n * Checks if the text is required to be truncated and broken into two lines based\n * on the available width of container. **Note: This is relevant to font size 18px or 1.125rem only **\n * @param text input text\n * @param widthOfElement element width in px\n */\n public static shouldTruncateToTwoLines(\n text: string,\n widthOfElement: number\n ): boolean {\n // This is arbitrary and based on tests to derive that every 9px increment ~= 1 char length.\n // But this applies to font size 18px or 1.125rem only\n const estimatedCharOnLine = Math.floor(widthOfElement / 9);\n return (\n text.length >= estimatedCharOnLine * 2 ||\n (text.split(\" \").length === 1 && text.length > estimatedCharOnLine)\n );\n }\n\n /**\n * Performs a truncation by adding ellipsis in the middle of the text.\n * @param text input text\n * @param widthOfElement the dynamic width of the container in px\n * @param minDivSize the minimum container size (using size on mobileS viewport as baseline)\n * @param baselineCharLength the baseline amount of characters to be displayed before truncation kicks. This\n * will be increased if there is more space available (derived from `widthOfElement`)\n * @param incrementFactor the size (in px).\n */\n public static truncateOneLine(\n text: string,\n widthOfElement: number,\n minDivSize: number,\n baselineCharLength: number,\n incrementFactor = 8 // Arbitrary based on tests and applies to font size of 18px or 1.125rem\n ): string {\n let additionalCharAllowed = 0;\n if (widthOfElement > minDivSize) {\n additionalCharAllowed = Math.floor(\n (widthOfElement - minDivSize) / incrementFactor\n );\n }\n const allowedCharLength = baselineCharLength + additionalCharAllowed;\n if (allowedCharLength < text.length) {\n const thresholdIndex = Math.floor(allowedCharLength / 2); // We will cut it halfway to derive x num of characters\n return (\n text.substring(0, thresholdIndex) + // Use the first x\n \" ... \" +\n text.substring(text.length - thresholdIndex, text.length) // Use the last x\n );\n }\n\n return text;\n }\n\n /**\n * Performs a truncation by adding ellipsis in the middle of the text.\n * @param text input text\n * @param widthOfElement the dynamic width of the container in px\n * @param fontSize the fontsize of the text\n * @param lineHeight the line height of the text\n */\n public static truncateTwoLines(\n text: string,\n widthOfElement: number,\n fontSize: number,\n lineHeight = 1.2\n ): string {\n // Estimate characters per line based on width and font size\n const charsPerLine = Math.floor(\n (widthOfElement * 2) / (fontSize * 0.6) // 0.6 is an approximation for average char width\n );\n\n // Calculate total characters allowed in two lines\n const totalCharsAllowed = charsPerLine * (2 / lineHeight);\n\n if (text.length <= totalCharsAllowed) {\n return text; // No truncation needed\n }\n\n // Calculate the number of characters to keep\n const keepFromStart = Math.floor(totalCharsAllowed * 0.6); // Keep 60% from start\n const keepFromEnd = Math.floor(totalCharsAllowed * 0.2); // Keep 20% from end\n\n // Truncate the text\n const start = text.substring(0, keepFromStart);\n const end = text.substring(text.length - keepFromEnd);\n\n return `${start}...${end}`;\n }\n\n /**\n * Returns the width of the text in the specified font\n * https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393\n */\n public static getTextWidth(text: string, font: string): number {\n if (typeof document === \"undefined\") {\n return 0;\n }\n\n // create a reusable canvas object for better performance\n const canvas =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (this.getTextWidth as any).canvas ||\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ((this.getTextWidth as any).canvas =\n document.createElement(\"canvas\"));\n const context = canvas.getContext(\"2d\");\n context.font = font;\n\n const metrics = context.measureText(text);\n return metrics.width;\n }\n\n public static maskValue(value: string, options: MaskValueOptions): string {\n if (!value) {\n return value;\n }\n\n const {\n maskRange,\n unmaskRange,\n maskChar = \"•\",\n maskRegex,\n maskTransformer,\n } = options;\n\n if (maskTransformer) {\n return maskTransformer(value);\n } else if (maskRegex) {\n return value.replace(maskRegex, maskChar);\n } else if (maskRange) {\n const { startIndex, endIndex } = this.determineStartAndEndIndex(\n maskRange[0],\n maskRange[1]\n );\n return (\n value.substring(0, startIndex) +\n maskChar.repeat(\n value.substring(startIndex, endIndex + 1).length\n ) +\n value.substring(endIndex + 1)\n );\n } else if (unmaskRange) {\n const { startIndex, endIndex } = this.determineStartAndEndIndex(\n unmaskRange[0],\n unmaskRange[1]\n );\n return (\n maskChar.repeat(value.substring(0, startIndex).length) +\n value.substring(startIndex, endIndex + 1) +\n maskChar.repeat(value.substring(endIndex + 1).length)\n );\n }\n\n return value;\n }\n\n private static determineStartAndEndIndex(index0: number, index1: number) {\n return index0 < index1\n ? { startIndex: index0, endIndex: index1 }\n : { startIndex: index1, endIndex: index0 };\n }\n\n private static readonly ordinalPluralRules = new Intl.PluralRules(\"en\", {\n type: \"ordinal\",\n });\n\n private static readonly suffixes = new Map([\n [\"one\", \"st\"],\n [\"two\", \"nd\"],\n [\"few\", \"rd\"],\n [\"other\", \"th\"],\n ]);\n\n public static formatOrdinal(n: number) {\n const rule = this.ordinalPluralRules.select(n);\n const suffix = this.suffixes.get(rule);\n return `${n}${suffix}`;\n }\n\n public static getMaskedDescription(\n value: string,\n displayMaskState: \"masked\" | \"unmasked\",\n maskRange?: number[]\n ): string {\n if (!value || displayMaskState !== \"masked\" || !maskRange) return \"\";\n\n const [startIndex, endIndex] = maskRange;\n const hasStart = startIndex > 0;\n const hasEnd = endIndex < value.length - 1;\n\n const start = hasStart ? value.substring(0, startIndex) : \"\";\n const end = hasEnd ? value.substring(endIndex + 1) : \"\";\n\n if (hasStart && hasEnd)\n return `Starting with ${start} and ending with ${end}`;\n if (hasStart) return `Starting with ${start}`;\n if (hasEnd) return `Ending with ${end}`;\n\n return \"\";\n }\n\n public static joinNonEmptyStrings(\n strings: (string | undefined | null)[],\n delimiter = \", \"\n ): string {\n return strings.filter(Boolean).join(delimiter);\n }\n}\n"],"names":["StringHelper","transformWithSpaces","value","groupLength","regex","replace","RegExp","trim","padValue","retainSingleZero","padStart","parseInt","toString","shouldTruncateToTwoLines","text","widthOfElement","estimatedCharOnLine","Math","floor","length","split","truncateOneLine","minDivSize","baselineCharLength","incrementFactor","additionalCharAllowed","allowedCharLength","thresholdIndex","substring","truncateTwoLines","fontSize","lineHeight","totalCharsAllowed","keepFromStart","keepFromEnd","getTextWidth","font","document","context","this","canvas","createElement","getContext","measureText","width","maskValue","options","maskRange","unmaskRange","maskChar","maskRegex","maskTransformer","startIndex","endIndex","determineStartAndEndIndex","repeat","index0","index1","formatOrdinal","n","rule","ordinalPluralRules","select","suffixes","get","getMaskedDescription","displayMaskState","hasStart","hasEnd","start","end","joinNonEmptyStrings","strings","delimiter","filter","Boolean","join","Intl","PluralRules","type","Map"],"mappings":"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"}