@ahrowe/ui 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/esm/common/actionButtons/actionButtons.mjs +1 -1
  2. package/dist/esm/common/actionButtons/actionButtons.mjs.map +1 -1
  3. package/dist/esm/common/alert/alert.mjs +1 -1
  4. package/dist/esm/common/alert/alert.mjs.map +1 -1
  5. package/dist/esm/common/alert/alert.types.mjs.map +1 -1
  6. package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
  7. package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
  8. package/dist/esm/common/card/Card.mjs +1 -1
  9. package/dist/esm/common/card/Card.mjs.map +1 -1
  10. package/dist/esm/common/card/card.types.mjs.map +1 -1
  11. package/dist/esm/common/carousel/carousel.mjs +1 -1
  12. package/dist/esm/common/carousel/carousel.mjs.map +1 -1
  13. package/dist/esm/common/chip/chip.mjs +1 -1
  14. package/dist/esm/common/chip/chip.mjs.map +1 -1
  15. package/dist/esm/common/chip/chip.types.mjs.map +1 -1
  16. package/dist/esm/common/colorPicker/colorPicker.mjs +1 -1
  17. package/dist/esm/common/colorPicker/colorPicker.mjs.map +1 -1
  18. package/dist/esm/common/configProvider/useLabels.mjs +2 -0
  19. package/dist/esm/common/configProvider/useLabels.mjs.map +1 -0
  20. package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
  21. package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
  22. package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
  23. package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs.map +1 -1
  24. package/dist/esm/common/datePicker/datePicker.mjs +1 -1
  25. package/dist/esm/common/datePicker/datePicker.mjs.map +1 -1
  26. package/dist/esm/common/drawer/drawer.mjs +1 -1
  27. package/dist/esm/common/drawer/drawer.mjs.map +1 -1
  28. package/dist/esm/common/dropdown/dropdown.mjs +1 -1
  29. package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
  30. package/dist/esm/common/emptyState/emptyState.mjs +1 -1
  31. package/dist/esm/common/emptyState/emptyState.mjs.map +1 -1
  32. package/dist/esm/common/fab/components/fabBase/fabBase.mjs +1 -1
  33. package/dist/esm/common/fab/components/fabBase/fabBase.mjs.map +1 -1
  34. package/dist/esm/common/fab/fab.mjs +1 -1
  35. package/dist/esm/common/fab/fab.mjs.map +1 -1
  36. package/dist/esm/common/infiniteBlock/infiniteBlock.mjs +1 -1
  37. package/dist/esm/common/infiniteBlock/infiniteBlock.mjs.map +1 -1
  38. package/dist/esm/common/input/input.mjs +1 -1
  39. package/dist/esm/common/input/input.mjs.map +1 -1
  40. package/dist/esm/common/input/input.types.mjs.map +1 -1
  41. package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
  42. package/dist/esm/common/klipyPicker/klipyPicker.mjs.map +1 -1
  43. package/dist/esm/common/modal/modal.mjs +1 -1
  44. package/dist/esm/common/modal/modal.mjs.map +1 -1
  45. package/dist/esm/common/multiSelect/multiSelect.mjs +1 -1
  46. package/dist/esm/common/multiSelect/multiSelect.mjs.map +1 -1
  47. package/dist/esm/common/numberInput/numberInput.mjs +1 -1
  48. package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
  49. package/dist/esm/common/otpInput/otpInput.mjs +1 -1
  50. package/dist/esm/common/otpInput/otpInput.mjs.map +1 -1
  51. package/dist/esm/common/otpInput/otpInput.types.mjs.map +1 -1
  52. package/dist/esm/common/pagination/pagination.mjs +1 -1
  53. package/dist/esm/common/pagination/pagination.mjs.map +1 -1
  54. package/dist/esm/common/progressBar/progressBar.mjs +1 -1
  55. package/dist/esm/common/progressBar/progressBar.mjs.map +1 -1
  56. package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
  57. package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
  58. package/dist/esm/common/searchInput/searchInput.mjs +1 -1
  59. package/dist/esm/common/searchInput/searchInput.mjs.map +1 -1
  60. package/dist/esm/common/splitButton/splitButton.mjs +1 -1
  61. package/dist/esm/common/splitButton/splitButton.mjs.map +1 -1
  62. package/dist/esm/common/timer/timer.mjs +1 -1
  63. package/dist/esm/common/timer/timer.mjs.map +1 -1
  64. package/dist/esm/common/toast/toast.mjs +1 -1
  65. package/dist/esm/common/toast/toast.mjs.map +1 -1
  66. package/dist/esm/common/toast/toastProvider.mjs +1 -1
  67. package/dist/esm/common/toast/toastProvider.mjs.map +1 -1
  68. package/dist/esm/common/tree/tree.mjs +1 -1
  69. package/dist/esm/common/tree/tree.mjs.map +1 -1
  70. package/dist/esm/common/virtualList/virtualList.mjs +1 -1
  71. package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
  72. package/dist/esm/common/virtualList/virtualListHeader.mjs +1 -1
  73. package/dist/esm/common/virtualList/virtualListHeader.mjs.map +1 -1
  74. package/dist/esm/index.mjs +1 -1
  75. package/dist/index.cjs +3 -3
  76. package/dist/index.cjs.map +1 -1
  77. package/dist/types/common/actionButtons/actionButtons.types.d.ts +9 -2
  78. package/dist/types/common/alert/alert.types.d.ts +7 -0
  79. package/dist/types/common/breadcrumb/breadcrumb.types.d.ts +7 -0
  80. package/dist/types/common/card/card.types.d.ts +6 -1
  81. package/dist/types/common/carousel/carousel.types.d.ts +13 -0
  82. package/dist/types/common/chip/chip.types.d.ts +13 -2
  83. package/dist/types/common/colorPicker/colorPicker.d.ts +1 -1
  84. package/dist/types/common/colorPicker/colorPicker.types.d.ts +13 -1
  85. package/dist/types/common/configProvider/configProvider.types.d.ts +26 -1
  86. package/dist/types/common/configProvider/index.d.ts +1 -0
  87. package/dist/types/common/configProvider/useLabels.d.ts +22 -0
  88. package/dist/types/common/confirmModal/confirmModal.types.d.ts +13 -4
  89. package/dist/types/common/datePicker/components/datePickerMonth/datePickerMonth.d.ts +2 -14
  90. package/dist/types/common/datePicker/components/datePickerMonth/datePickerMonth.types.d.ts +23 -0
  91. package/dist/types/common/datePicker/datePicker.d.ts +1 -22
  92. package/dist/types/common/datePicker/datePicker.types.d.ts +60 -0
  93. package/dist/types/common/datePicker/index.d.ts +1 -0
  94. package/dist/types/common/drawer/drawer.d.ts +1 -1
  95. package/dist/types/common/drawer/drawer.types.d.ts +7 -1
  96. package/dist/types/common/dropdown/dropdown.types.d.ts +6 -6
  97. package/dist/types/common/emptyState/emptyState.d.ts +1 -1
  98. package/dist/types/common/emptyState/emptyState.types.d.ts +13 -1
  99. package/dist/types/common/fab/components/fabBase/fabBase.d.ts +1 -1
  100. package/dist/types/common/fab/components/fabBase/fabBase.types.d.ts +3 -1
  101. package/dist/types/common/fab/fab.d.ts +1 -1
  102. package/dist/types/common/fab/fab.types.d.ts +6 -1
  103. package/dist/types/common/infiniteBlock/infiniteBlock.d.ts +1 -1
  104. package/dist/types/common/infiniteBlock/infiniteBlock.types.d.ts +2 -0
  105. package/dist/types/common/input/input.types.d.ts +13 -0
  106. package/dist/types/common/klipyPicker/klipyPicker.d.ts +1 -1
  107. package/dist/types/common/klipyPicker/klipyPicker.types.d.ts +7 -0
  108. package/dist/types/common/modal/modal.types.d.ts +7 -0
  109. package/dist/types/common/multiSelect/multiSelect.types.d.ts +13 -6
  110. package/dist/types/common/numberInput/numberInput.types.d.ts +15 -2
  111. package/dist/types/common/otpInput/otpInput.types.d.ts +9 -0
  112. package/dist/types/common/pagination/pagination.types.d.ts +15 -0
  113. package/dist/types/common/progressBar/progressBar.d.ts +1 -1
  114. package/dist/types/common/progressBar/progressBar.types.d.ts +6 -1
  115. package/dist/types/common/roomDrawer/roomDrawer.types.d.ts +6 -0
  116. package/dist/types/common/searchInput/searchInput.d.ts +1 -1
  117. package/dist/types/common/searchInput/searchInput.types.d.ts +13 -1
  118. package/dist/types/common/splitButton/splitButton.types.d.ts +7 -0
  119. package/dist/types/common/timer/timer.types.d.ts +7 -0
  120. package/dist/types/common/toast/toast.d.ts +4 -2
  121. package/dist/types/common/toast/toast.types.d.ts +11 -1
  122. package/dist/types/common/toast/toastProvider.d.ts +1 -1
  123. package/dist/types/common/tree/tree.types.d.ts +7 -2
  124. package/dist/types/common/virtualList/virtualList.types.d.ts +15 -6
  125. package/dist/types/common/virtualList/virtualListHeader.d.ts +3 -3
  126. package/docs/ActionButtons.md +7 -6
  127. package/docs/Alert.md +2 -0
  128. package/docs/Breadcrumb.md +2 -0
  129. package/docs/Card.md +2 -0
  130. package/docs/Carousel.md +2 -0
  131. package/docs/Chip.md +5 -1
  132. package/docs/ColorPicker.md +4 -0
  133. package/docs/ConfigProvider.md +23 -0
  134. package/docs/ConfirmModal.md +7 -5
  135. package/docs/DatePicker.md +6 -1
  136. package/docs/Drawer.md +2 -0
  137. package/docs/Dropdown.md +2 -0
  138. package/docs/EmptyState.md +4 -0
  139. package/docs/Fab.md +2 -0
  140. package/docs/FormValidatorGroup.md +1 -1
  141. package/docs/Input.md +2 -0
  142. package/docs/KlipyPicker.md +2 -0
  143. package/docs/Modal.md +2 -0
  144. package/docs/MultiSelect.md +7 -5
  145. package/docs/NumberInput.md +8 -2
  146. package/docs/OtpInput.md +2 -0
  147. package/docs/Pagination.md +2 -0
  148. package/docs/ProgressBar.md +2 -0
  149. package/docs/RoomDrawer.md +2 -0
  150. package/docs/SearchInput.md +4 -0
  151. package/docs/SplitButton.md +2 -0
  152. package/docs/Timer.md +2 -0
  153. package/docs/Toast.md +2 -0
  154. package/docs/Tree.md +3 -1
  155. package/docs/VirtualList.md +3 -2
  156. package/docs/Wizard.md +1 -2
  157. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../tooltip/tooltip.mjs";import{OtpInputCharset as n}from"./otpInput.types.mjs";import r from"./otpInput.module.mjs";import{useEffect as i,useRef as a,useState as o}from"react";import s from"classnames";import{jsx as c,jsxs as l}from"react/jsx-runtime";var u=/[0-9]/g,d=/[a-zA-Z0-9]/g;function f(e,t){let r=t===n.Alphanumeric?d:u;return(e.match(r)||[]).join(``)}function p(u){let{length:d=6,value:p,onChange:m=()=>{},onComplete:h=()=>{},formValidator:g=null,charset:_=n.Numeric,masked:v=!1,groupAfter:y=[],label:b=``,isValid:x=!0,errorMessage:S=``,isRequired:C=!1,clearOnError:w=!1,clearErrorDelay:T=900,disabled:E=!1,autoFocus:D=!1,className:O=``,style:k,classNames:A,styles:j,...M}=e(`OtpInput`,u),N=(g?g.value:p)??``,[,P]=o(0),[F,I]=o(!1),[L,R]=o(!1),[z,B]=o(!1),V=a([]),H=a(!1);i(()=>{if(!g)return;g.validate();let e=()=>P(e=>e+1);return g.registerOnUpdateListener(e),()=>g.removeOnUpdateListener(e)},[g]),i(()=>{if(!D)return;let e=Math.min(N.length,d-1);V.current[e]?.focus()},[]);let U=g?g.touched&&g.hasError():!x||!!S,W=g?g.getCurrentErrorMessage():S||``;i(()=>{let e=U&&!H.current;if(H.current=U,!e)return;I(!0);let t=window.setTimeout(()=>I(!1),400),n=w?window.setTimeout(()=>{G(``),V.current[0]?.focus()},T):null;return()=>{window.clearTimeout(t),n!=null&&window.clearTimeout(n)}},[U,w,T]);function G(e){let t=N.length===d,n=f(e,_).slice(0,d);g&&g.set(n),m?.(n),n.length===d&&!t&&h?.(n)}function K(e,t){let n=N.split(``);n[e]=t,G(n.join(``))}function q(e,t){if(E)return;if(t===``){K(e,``);return}let n=f(t,_);if(!n)return;let r=Math.min(e,N.length);if(t.length>1){J(r,n);return}K(r,n),r<d-1?V.current[r+1]?.focus():V.current[r]?.blur()}function J(e,t){let n=f(t,_);if(!n)return;let r=N.padEnd(d,` `).split(``),i=e;for(let e of n){if(i>=d)break;r[i]=e,i+=1}G(r.join(``).trimEnd());let a=Math.min(i,d-1);V.current[a]?.focus(),i>=d&&V.current[d-1]?.blur()}function Y(e,t){if(E)return;let n=t.clipboardData.getData(`text`);n&&(t.preventDefault(),J(Math.min(e,N.length),n))}function X(e,t){if(!E){if(t.key.length===1&&!t.ctrlKey&&!t.metaKey&&!t.altKey){let n=f(t.key,_);if(n&&N[e]===n){t.preventDefault(),K(e,n),e<d-1?V.current[e+1]?.focus():V.current[e]?.blur();return}}if(t.key===`Backspace`){if(N[e]){K(e,``);return}e>0&&(t.preventDefault(),K(e-1,``),V.current[e-1]?.focus());return}if(t.key===`Delete`){N[e]&&K(e,``);return}if(t.key===`ArrowLeft`&&e>0){t.preventDefault(),V.current[e-1]?.focus();return}t.key===`ArrowRight`&&e<d-1&&(t.preventDefault(),V.current[e+1]?.focus())}}function Z(e){e.target.select()}function Q(){R(!0)}function $(e){e.currentTarget.contains(e.relatedTarget)||(R(!1),g&&(g.touched=!0))}return l(`div`,{...M,className:s(r.otpInput,E&&r.otpInputDisabled,O),style:k,children:[b&&l(`div`,{className:s(r.otpInputLabel,A?.label),style:j?.label,children:[b,C&&c(`span`,{className:r.otpInputRequiredMark,children:` *`})]}),c(`div`,{role:`group`,"aria-label":b||`One-time code`,className:s(r.otpInputBoxes,F&&r.otpInputBoxesShake,A?.inputs),style:j?.inputs,onFocus:Q,onBlur:$,onMouseEnter:()=>B(!0),onMouseLeave:()=>B(!1),children:Array.from({length:d},(e,t)=>{let i=N[t]||``;return l(`div`,{className:r.otpInputBoxWrapper,children:[c(`input`,{ref:e=>{V.current[t]=e},type:v?`password`:`text`,inputMode:_===n.Numeric?`numeric`:`text`,pattern:_===n.Numeric?`[0-9]*`:void 0,autoComplete:t===0?`one-time-code`:`off`,maxLength:1,disabled:E,value:i,"aria-label":`Digit ${t+1} of ${d}`,"aria-invalid":U||void 0,className:s(r.otpInputBox,U&&r.otpInputBoxError,i&&r.otpInputBoxFilled,A?.input),style:j?.input,onChange:e=>q(t,e.target.value),onKeyDown:e=>X(t,e),onPaste:e=>Y(t,e),onFocus:Z}),y.includes(t+1)&&t<d-1&&c(`span`,{className:s(r.otpInputSeparator,A?.separator),style:j?.separator})]},t)})}),c(t,{variant:`error`,message:W,isVisible:U&&(L||z)})]})}export{p as default};
1
+ import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import n from"../tooltip/tooltip.mjs";import{OtpInputCharset as r}from"./otpInput.types.mjs";import i from"./otpInput.module.mjs";import{useEffect as a,useRef as o,useState as s}from"react";import c from"classnames";import{jsx as l,jsxs as u}from"react/jsx-runtime";var d=/[0-9]/g,f=/[a-zA-Z0-9]/g,p={field:`One-time code`,digit:(e,t)=>`Digit ${e} of ${t}`};function m(e,t){let n=t===r.Alphanumeric?f:d;return(e.match(n)||[]).join(``)}function h(d){let{length:f=6,value:h,onChange:g=()=>{},onComplete:_=()=>{},formValidator:v=null,charset:y=r.Numeric,masked:b=!1,groupAfter:x=[],label:S=``,isValid:C=!0,errorMessage:w=``,isRequired:T=!1,clearOnError:E=!1,clearErrorDelay:D=900,disabled:O=!1,autoFocus:k=!1,className:A=``,style:j,classNames:M,styles:N,labels:P,...F}=e(`OtpInput`,d),I=t(`OtpInput`,P,p),L=(v?v.value:h)??``,[,R]=s(0),[z,B]=s(!1),[V,H]=s(!1),[U,W]=s(!1),G=o([]),K=o(!1);a(()=>{if(!v)return;v.validate();let e=()=>R(e=>e+1);return v.registerOnUpdateListener(e),()=>v.removeOnUpdateListener(e)},[v]),a(()=>{if(!k)return;let e=Math.min(L.length,f-1);G.current[e]?.focus()},[]);let q=v?v.touched&&v.hasError():!C||!!w,J=v?v.getCurrentErrorMessage():w||``;a(()=>{let e=q&&!K.current;if(K.current=q,!e)return;B(!0);let t=window.setTimeout(()=>B(!1),400),n=E?window.setTimeout(()=>{Y(``),G.current[0]?.focus()},D):null;return()=>{window.clearTimeout(t),n!=null&&window.clearTimeout(n)}},[q,E,D]);function Y(e){let t=L.length===f,n=m(e,y).slice(0,f);v&&v.set(n),g?.(n),n.length===f&&!t&&_?.(n)}function X(e,t){let n=L.split(``);n[e]=t,Y(n.join(``))}function Z(e,t){if(O)return;if(t===``){X(e,``);return}let n=m(t,y);if(!n)return;let r=Math.min(e,L.length);if(t.length>1){Q(r,n);return}X(r,n),r<f-1?G.current[r+1]?.focus():G.current[r]?.blur()}function Q(e,t){let n=m(t,y);if(!n)return;let r=L.padEnd(f,` `).split(``),i=e;for(let e of n){if(i>=f)break;r[i]=e,i+=1}Y(r.join(``).trimEnd());let a=Math.min(i,f-1);G.current[a]?.focus(),i>=f&&G.current[f-1]?.blur()}function $(e,t){if(O)return;let n=t.clipboardData.getData(`text`);n&&(t.preventDefault(),Q(Math.min(e,L.length),n))}function ee(e,t){if(!O){if(t.key.length===1&&!t.ctrlKey&&!t.metaKey&&!t.altKey){let n=m(t.key,y);if(n&&L[e]===n){t.preventDefault(),X(e,n),e<f-1?G.current[e+1]?.focus():G.current[e]?.blur();return}}if(t.key===`Backspace`){if(L[e]){X(e,``);return}e>0&&(t.preventDefault(),X(e-1,``),G.current[e-1]?.focus());return}if(t.key===`Delete`){L[e]&&X(e,``);return}if(t.key===`ArrowLeft`&&e>0){t.preventDefault(),G.current[e-1]?.focus();return}t.key===`ArrowRight`&&e<f-1&&(t.preventDefault(),G.current[e+1]?.focus())}}function te(e){e.target.select()}function ne(){H(!0)}function re(e){e.currentTarget.contains(e.relatedTarget)||(H(!1),v&&(v.touched=!0))}return u(`div`,{...F,className:c(i.otpInput,O&&i.otpInputDisabled,A),style:j,children:[S&&u(`div`,{className:c(i.otpInputLabel,M?.label),style:N?.label,children:[S,T&&l(`span`,{className:i.otpInputRequiredMark,children:` *`})]}),l(`div`,{role:`group`,"aria-label":S||I.field,className:c(i.otpInputBoxes,z&&i.otpInputBoxesShake,M?.inputs),style:N?.inputs,onFocus:ne,onBlur:re,onMouseEnter:()=>W(!0),onMouseLeave:()=>W(!1),children:Array.from({length:f},(e,t)=>{let n=L[t]||``;return u(`div`,{className:i.otpInputBoxWrapper,children:[l(`input`,{ref:e=>{G.current[t]=e},type:b?`password`:`text`,inputMode:y===r.Numeric?`numeric`:`text`,pattern:y===r.Numeric?`[0-9]*`:void 0,autoComplete:t===0?`one-time-code`:`off`,maxLength:1,disabled:O,value:n,"aria-label":I.digit(t+1,f),"aria-invalid":q||void 0,className:c(i.otpInputBox,q&&i.otpInputBoxError,n&&i.otpInputBoxFilled,M?.input),style:N?.input,onChange:e=>Z(t,e.target.value),onKeyDown:e=>ee(t,e),onPaste:e=>$(t,e),onFocus:te}),x.includes(t+1)&&t<f-1&&l(`span`,{className:c(i.otpInputSeparator,M?.separator),style:N?.separator})]},t)})}),l(n,{variant:`error`,message:J,isVisible:q&&(V||U)})]})}export{h as default};
2
2
  //# sourceMappingURL=otpInput.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"otpInput.mjs","names":[],"sources":["../../../../package/common/otpInput/otpInput.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Tooltip from 'components/common/tooltip';\nimport { useComponentDefaults } from '../configProvider';\n\nimport { OtpInputCharset, type OtpInputProps } from './otpInput.types';\nimport styles from './otpInput.module.pcss';\n\nconst NUMERIC_RE = /[0-9]/g;\nconst ALPHANUMERIC_RE = /[a-zA-Z0-9]/g;\n\nfunction filterChars(raw: string, charset: OtpInputCharset): string {\n const re = charset === OtpInputCharset.Alphanumeric ? ALPHANUMERIC_RE : NUMERIC_RE;\n return (raw.match(re) || []).join('');\n}\n\nfunction OtpInput(props: OtpInputProps): ReactElement {\n const {\n length = 6,\n value,\n onChange = () => {},\n onComplete = () => {},\n formValidator = null,\n charset = OtpInputCharset.Numeric,\n masked = false,\n groupAfter = [],\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n clearOnError = false,\n clearErrorDelay = 900,\n disabled = false,\n autoFocus = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('OtpInput', props);\n\n const currentValue = (formValidator ? (formValidator.value as string) : value) ?? '';\n const [, forceUpdate] = useState(0);\n const [isShaking, setIsShaking] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const inputRefs = useRef<Array<HTMLInputElement | null>>([]);\n const wasErrorRef = useRef(false);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.validate();\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n useEffect(() => {\n if (!autoFocus) return;\n const firstEmpty = Math.min(currentValue.length, length - 1);\n inputRefs.current[firstEmpty]?.focus();\n // Only run once, on mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const showError = formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n const displayedErrorMessage = formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || '';\n\n useEffect(() => {\n const justErrored = showError && !wasErrorRef.current;\n wasErrorRef.current = showError;\n if (!justErrored) return;\n\n setIsShaking(true);\n const shakeTimeoutId = window.setTimeout(() => setIsShaking(false), 400);\n const clearTimeoutId = clearOnError\n ? window.setTimeout(() => {\n commit('');\n inputRefs.current[0]?.focus();\n }, clearErrorDelay)\n : null;\n\n return () => {\n window.clearTimeout(shakeTimeoutId);\n if (clearTimeoutId != null) window.clearTimeout(clearTimeoutId);\n };\n // Only re-evaluate on an actual error-state or config change, not on every value/render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showError, clearOnError, clearErrorDelay]);\n\n function commit(next: string) {\n const wasComplete = currentValue.length === length;\n const clipped = filterChars(next, charset).slice(0, length);\n if (formValidator) {\n formValidator.set(clipped);\n }\n onChange?.(clipped);\n // Only fire once per genuinely new completion (going from partial to full), not on every\n // keystroke made while correcting an already-full code.\n if (clipped.length === length && !wasComplete) {\n onComplete?.(clipped);\n }\n }\n\n function setCharAt(index: number, char: string) {\n const chars = currentValue.split('');\n chars[index] = char;\n commit(chars.join(''));\n }\n\n function handleChange(index: number, rawInput: string) {\n if (disabled) return;\n if (rawInput === '') {\n // Box was cleared (e.g. select + delete) — Backspace itself is handled in onKeyDown.\n setCharAt(index, '');\n return;\n }\n\n const filtered = filterChars(rawInput, charset);\n if (!filtered) {\n // Typed an invalid/disallowed character — the controlled `value` re-render discards it.\n return;\n }\n\n // Clicking straight into a box past the contiguous filled prefix (skipping ahead of\n // empty boxes) fills the next expected slot instead, rather than leaving a gap before it\n // that setCharAt/distributeFrom can't represent in a plain string and would silently collapse.\n const targetIndex = Math.min(index, currentValue.length);\n\n if (rawInput.length > 1) {\n // Mobile autofill / SMS suggestions can drop the whole code into one box, bypassing maxLength.\n distributeFrom(targetIndex, filtered);\n return;\n }\n\n setCharAt(targetIndex, filtered);\n if (targetIndex < length - 1) {\n inputRefs.current[targetIndex + 1]?.focus();\n } else {\n inputRefs.current[targetIndex]?.blur();\n }\n }\n\n function distributeFrom(startIndex: number, chars: string) {\n const clean = filterChars(chars, charset);\n if (!clean) return;\n const existing = currentValue.padEnd(length, ' ').split('');\n let cursor = startIndex;\n for (const char of clean) {\n if (cursor >= length) break;\n existing[cursor] = char;\n cursor += 1;\n }\n commit(existing.join('').trimEnd());\n const nextFocus = Math.min(cursor, length - 1);\n inputRefs.current[nextFocus]?.focus();\n if (cursor >= length) {\n inputRefs.current[length - 1]?.blur();\n }\n }\n\n function handlePaste(index: number, event: React.ClipboardEvent<HTMLInputElement>) {\n if (disabled) return;\n const pasted = event.clipboardData.getData('text');\n if (!pasted) return;\n event.preventDefault();\n // Same clamp as handleChange — pasting into a box past the filled prefix starts at the\n // next expected slot instead of leaving an unrepresentable gap before it.\n distributeFrom(Math.min(index, currentValue.length), pasted);\n }\n\n function handleKeyDown(index: number, event: React.KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n\n // React's controlled-input onChange never fires when the resulting value is identical to\n // what's already rendered (its value tracker sees no change) — so retyping the exact digit\n // already in a box would otherwise silently do nothing. keydown always fires, so handle that\n // one case here and skip the native edit entirely.\n if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {\n const typed = filterChars(event.key, charset);\n if (typed && currentValue[index] === typed) {\n event.preventDefault();\n setCharAt(index, typed);\n if (index < length - 1) {\n inputRefs.current[index + 1]?.focus();\n } else {\n inputRefs.current[index]?.blur();\n }\n return;\n }\n }\n\n if (event.key === 'Backspace') {\n if (currentValue[index]) {\n setCharAt(index, '');\n return;\n }\n if (index > 0) {\n event.preventDefault();\n setCharAt(index - 1, '');\n inputRefs.current[index - 1]?.focus();\n }\n return;\n }\n if (event.key === 'Delete') {\n if (currentValue[index]) setCharAt(index, '');\n return;\n }\n if (event.key === 'ArrowLeft' && index > 0) {\n event.preventDefault();\n inputRefs.current[index - 1]?.focus();\n return;\n }\n if (event.key === 'ArrowRight' && index < length - 1) {\n event.preventDefault();\n inputRefs.current[index + 1]?.focus();\n }\n }\n\n function handleFocus(event: React.FocusEvent<HTMLInputElement>) {\n event.target.select();\n }\n\n function handleGroupFocus() {\n setIsFocused(true);\n }\n\n function handleGroupBlur(event: React.FocusEvent<HTMLDivElement>) {\n // Auto-advance moves focus between boxes constantly while typing — only treat this as\n // leaving the group once focus actually lands outside it, not on the next box.\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n setIsFocused(false);\n if (formValidator) formValidator.touched = true;\n }\n\n return (\n <div {...rest} className={cx(styles.otpInput, disabled && styles.otpInputDisabled, className)} style={style}>\n {label && (\n <div className={cx(styles.otpInputLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n {isRequired && <span className={styles.otpInputRequiredMark}> *</span>}\n </div>\n )}\n <div\n role='group'\n aria-label={label || 'One-time code'}\n className={cx(styles.otpInputBoxes, isShaking && styles.otpInputBoxesShake, classNames?.inputs)}\n style={slotStyles?.inputs}\n onFocus={handleGroupFocus}\n onBlur={handleGroupBlur}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {Array.from({ length }, (_, index) => {\n const char = currentValue[index] || '';\n return (\n <div key={index} className={styles.otpInputBoxWrapper}>\n <input\n ref={(el) => {\n inputRefs.current[index] = el;\n }}\n type={masked ? 'password' : 'text'}\n inputMode={charset === OtpInputCharset.Numeric ? 'numeric' : 'text'}\n pattern={charset === OtpInputCharset.Numeric ? '[0-9]*' : undefined}\n autoComplete={index === 0 ? 'one-time-code' : 'off'}\n maxLength={1}\n disabled={disabled}\n value={char}\n aria-label={`Digit ${index + 1} of ${length}`}\n aria-invalid={showError || undefined}\n className={cx(\n styles.otpInputBox,\n showError && styles.otpInputBoxError,\n char && styles.otpInputBoxFilled,\n classNames?.input,\n )}\n style={slotStyles?.input}\n onChange={(e) => handleChange(index, e.target.value)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n onPaste={(e) => handlePaste(index, e)}\n onFocus={handleFocus}\n />\n {groupAfter.includes(index + 1) && index < length - 1 && (\n <span className={cx(styles.otpInputSeparator, classNames?.separator)} style={slotStyles?.separator} />\n )}\n </div>\n );\n })}\n </div>\n <Tooltip variant='error' message={displayedErrorMessage} isVisible={showError && (isFocused || isHovered)} />\n </div>\n );\n}\n\nexport default OtpInput;\n"],"mappings":"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"}
1
+ {"version":3,"file":"otpInput.mjs","names":[],"sources":["../../../../package/common/otpInput/otpInput.tsx"],"sourcesContent":["import { useEffect, useRef, useState, type ReactElement } from 'react';\nimport cx from 'classnames';\nimport Tooltip from 'components/common/tooltip';\nimport { useComponentDefaults, useLabels } from '../configProvider';\n\nimport { OtpInputCharset, type OtpInputLabels, type OtpInputProps } from './otpInput.types';\nimport styles from './otpInput.module.pcss';\n\nconst NUMERIC_RE = /[0-9]/g;\nconst ALPHANUMERIC_RE = /[a-zA-Z0-9]/g;\n\nconst DEFAULT_LABELS: Required<OtpInputLabels> = {\n field: 'One-time code',\n digit: (position, length) => `Digit ${position} of ${length}`,\n};\n\nfunction filterChars(raw: string, charset: OtpInputCharset): string {\n const re = charset === OtpInputCharset.Alphanumeric ? ALPHANUMERIC_RE : NUMERIC_RE;\n return (raw.match(re) || []).join('');\n}\n\nfunction OtpInput(props: OtpInputProps): ReactElement {\n const {\n length = 6,\n value,\n onChange = () => {},\n onComplete = () => {},\n formValidator = null,\n charset = OtpInputCharset.Numeric,\n masked = false,\n groupAfter = [],\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n clearOnError = false,\n clearErrorDelay = 900,\n disabled = false,\n autoFocus = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('OtpInput', props);\n const text = useLabels('OtpInput', labels, DEFAULT_LABELS);\n\n const currentValue = (formValidator ? (formValidator.value as string) : value) ?? '';\n const [, forceUpdate] = useState(0);\n const [isShaking, setIsShaking] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const inputRefs = useRef<Array<HTMLInputElement | null>>([]);\n const wasErrorRef = useRef(false);\n\n useEffect(() => {\n if (!formValidator) return;\n formValidator.validate();\n const listener = () => forceUpdate((n) => n + 1);\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n useEffect(() => {\n if (!autoFocus) return;\n const firstEmpty = Math.min(currentValue.length, length - 1);\n inputRefs.current[firstEmpty]?.focus();\n // Only run once, on mount.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const showError = formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n const displayedErrorMessage = formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || '';\n\n useEffect(() => {\n const justErrored = showError && !wasErrorRef.current;\n wasErrorRef.current = showError;\n if (!justErrored) return;\n\n setIsShaking(true);\n const shakeTimeoutId = window.setTimeout(() => setIsShaking(false), 400);\n const clearTimeoutId = clearOnError\n ? window.setTimeout(() => {\n commit('');\n inputRefs.current[0]?.focus();\n }, clearErrorDelay)\n : null;\n\n return () => {\n window.clearTimeout(shakeTimeoutId);\n if (clearTimeoutId != null) window.clearTimeout(clearTimeoutId);\n };\n // Only re-evaluate on an actual error-state or config change, not on every value/render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showError, clearOnError, clearErrorDelay]);\n\n function commit(next: string) {\n const wasComplete = currentValue.length === length;\n const clipped = filterChars(next, charset).slice(0, length);\n if (formValidator) {\n formValidator.set(clipped);\n }\n onChange?.(clipped);\n // Only fire once per genuinely new completion (going from partial to full), not on every\n // keystroke made while correcting an already-full code.\n if (clipped.length === length && !wasComplete) {\n onComplete?.(clipped);\n }\n }\n\n function setCharAt(index: number, char: string) {\n const chars = currentValue.split('');\n chars[index] = char;\n commit(chars.join(''));\n }\n\n function handleChange(index: number, rawInput: string) {\n if (disabled) return;\n if (rawInput === '') {\n // Box was cleared (e.g. select + delete) — Backspace itself is handled in onKeyDown.\n setCharAt(index, '');\n return;\n }\n\n const filtered = filterChars(rawInput, charset);\n if (!filtered) {\n // Typed an invalid/disallowed character — the controlled `value` re-render discards it.\n return;\n }\n\n // Clicking straight into a box past the contiguous filled prefix (skipping ahead of\n // empty boxes) fills the next expected slot instead, rather than leaving a gap before it\n // that setCharAt/distributeFrom can't represent in a plain string and would silently collapse.\n const targetIndex = Math.min(index, currentValue.length);\n\n if (rawInput.length > 1) {\n // Mobile autofill / SMS suggestions can drop the whole code into one box, bypassing maxLength.\n distributeFrom(targetIndex, filtered);\n return;\n }\n\n setCharAt(targetIndex, filtered);\n if (targetIndex < length - 1) {\n inputRefs.current[targetIndex + 1]?.focus();\n } else {\n inputRefs.current[targetIndex]?.blur();\n }\n }\n\n function distributeFrom(startIndex: number, chars: string) {\n const clean = filterChars(chars, charset);\n if (!clean) return;\n const existing = currentValue.padEnd(length, ' ').split('');\n let cursor = startIndex;\n for (const char of clean) {\n if (cursor >= length) break;\n existing[cursor] = char;\n cursor += 1;\n }\n commit(existing.join('').trimEnd());\n const nextFocus = Math.min(cursor, length - 1);\n inputRefs.current[nextFocus]?.focus();\n if (cursor >= length) {\n inputRefs.current[length - 1]?.blur();\n }\n }\n\n function handlePaste(index: number, event: React.ClipboardEvent<HTMLInputElement>) {\n if (disabled) return;\n const pasted = event.clipboardData.getData('text');\n if (!pasted) return;\n event.preventDefault();\n // Same clamp as handleChange — pasting into a box past the filled prefix starts at the\n // next expected slot instead of leaving an unrepresentable gap before it.\n distributeFrom(Math.min(index, currentValue.length), pasted);\n }\n\n function handleKeyDown(index: number, event: React.KeyboardEvent<HTMLInputElement>) {\n if (disabled) return;\n\n // React's controlled-input onChange never fires when the resulting value is identical to\n // what's already rendered (its value tracker sees no change) — so retyping the exact digit\n // already in a box would otherwise silently do nothing. keydown always fires, so handle that\n // one case here and skip the native edit entirely.\n if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {\n const typed = filterChars(event.key, charset);\n if (typed && currentValue[index] === typed) {\n event.preventDefault();\n setCharAt(index, typed);\n if (index < length - 1) {\n inputRefs.current[index + 1]?.focus();\n } else {\n inputRefs.current[index]?.blur();\n }\n return;\n }\n }\n\n if (event.key === 'Backspace') {\n if (currentValue[index]) {\n setCharAt(index, '');\n return;\n }\n if (index > 0) {\n event.preventDefault();\n setCharAt(index - 1, '');\n inputRefs.current[index - 1]?.focus();\n }\n return;\n }\n if (event.key === 'Delete') {\n if (currentValue[index]) setCharAt(index, '');\n return;\n }\n if (event.key === 'ArrowLeft' && index > 0) {\n event.preventDefault();\n inputRefs.current[index - 1]?.focus();\n return;\n }\n if (event.key === 'ArrowRight' && index < length - 1) {\n event.preventDefault();\n inputRefs.current[index + 1]?.focus();\n }\n }\n\n function handleFocus(event: React.FocusEvent<HTMLInputElement>) {\n event.target.select();\n }\n\n function handleGroupFocus() {\n setIsFocused(true);\n }\n\n function handleGroupBlur(event: React.FocusEvent<HTMLDivElement>) {\n // Auto-advance moves focus between boxes constantly while typing — only treat this as\n // leaving the group once focus actually lands outside it, not on the next box.\n if (event.currentTarget.contains(event.relatedTarget as Node | null)) return;\n setIsFocused(false);\n if (formValidator) formValidator.touched = true;\n }\n\n return (\n <div {...rest} className={cx(styles.otpInput, disabled && styles.otpInputDisabled, className)} style={style}>\n {label && (\n <div className={cx(styles.otpInputLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n {isRequired && <span className={styles.otpInputRequiredMark}> *</span>}\n </div>\n )}\n <div\n role='group'\n aria-label={label || text.field}\n className={cx(styles.otpInputBoxes, isShaking && styles.otpInputBoxesShake, classNames?.inputs)}\n style={slotStyles?.inputs}\n onFocus={handleGroupFocus}\n onBlur={handleGroupBlur}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {Array.from({ length }, (_, index) => {\n const char = currentValue[index] || '';\n return (\n <div key={index} className={styles.otpInputBoxWrapper}>\n <input\n ref={(el) => {\n inputRefs.current[index] = el;\n }}\n type={masked ? 'password' : 'text'}\n inputMode={charset === OtpInputCharset.Numeric ? 'numeric' : 'text'}\n pattern={charset === OtpInputCharset.Numeric ? '[0-9]*' : undefined}\n autoComplete={index === 0 ? 'one-time-code' : 'off'}\n maxLength={1}\n disabled={disabled}\n value={char}\n aria-label={text.digit(index + 1, length)}\n aria-invalid={showError || undefined}\n className={cx(\n styles.otpInputBox,\n showError && styles.otpInputBoxError,\n char && styles.otpInputBoxFilled,\n classNames?.input,\n )}\n style={slotStyles?.input}\n onChange={(e) => handleChange(index, e.target.value)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n onPaste={(e) => handlePaste(index, e)}\n onFocus={handleFocus}\n />\n {groupAfter.includes(index + 1) && index < length - 1 && (\n <span className={cx(styles.otpInputSeparator, classNames?.separator)} style={slotStyles?.separator} />\n )}\n </div>\n );\n })}\n </div>\n <Tooltip variant='error' message={displayedErrorMessage} isVisible={showError && (isFocused || isHovered)} />\n </div>\n );\n}\n\nexport default OtpInput;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"otpInput.types.mjs","names":[],"sources":["../../../../package/common/otpInput/otpInput.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport type OtpInputSlots = 'root' | 'label' | 'inputs' | 'input' | 'separator';\n\nexport enum OtpInputCharset {\n /** Digits only (0-9). Shows a numeric mobile keyboard. */\n Numeric = 'numeric',\n /** Letters and digits. */\n Alphanumeric = 'alphanumeric',\n}\n\nexport interface OtpInputProps extends Omit<HtmlProps, 'onChange'> {\n /** Number of character boxes. Default 6. */\n length?: number;\n /** Current code as a plain string, e.g. \"123456\". */\n value?: string;\n /** Fired on every change with the full current code (may be shorter than `length`). */\n onChange?: ((value: string) => void) | null;\n /** Fired once, when the code reaches `length` characters. */\n onComplete?: ((value: string) => void) | null;\n formValidator?: FormValidator | null;\n\n /** Restricts which characters can be typed and picks the mobile keyboard. Default `numeric`. */\n charset?: OtpInputCharset;\n /** Render each box's value as a dot, like a password field. */\n masked?: boolean;\n /** Draw a small gap after these 1-based box indices, e.g. `[3]` to split 6 boxes into 3+3. */\n groupAfter?: number[];\n\n label?: string;\n isValid?: boolean;\n /** Shown in an error Tooltip on focus/hover once `isValid` is `false` (or, with a\n * `formValidator`, once it's touched and has an error). Persists until the value changes\n * `isValid`/`formValidator`'s error state itself — see `clearOnError` to auto-dismiss it. */\n errorMessage?: string;\n isRequired?: boolean;\n /** When an error newly appears (`isValid`/`formValidator` turning invalid), clear every box and\n * refocus the first one after `clearErrorDelay`, so the next attempt starts clean instead of the\n * user editing individual wrong digits (and re-triggering `onComplete` on every keystroke while\n * the code stays at full length). Default `false`. */\n clearOnError?: boolean;\n /** Delay in ms before `clearOnError` clears the boxes, so the wrong code and error message are\n * still visible for a moment first. Default `900`. */\n clearErrorDelay?: number;\n disabled?: boolean;\n /** Focuses the first empty box (or the first box) on mount. */\n autoFocus?: boolean;\n\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<OtpInputSlots>;\n styles?: SlotStyles<OtpInputSlots>;\n}\n"],"mappings":"AAMA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,QAAA,UAEA,EAAA,aAAA,gBACF,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"otpInput.types.mjs","names":[],"sources":["../../../../package/common/otpInput/otpInput.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { FormValidator } from 'services/formValidation';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\nexport type OtpInputSlots = 'root' | 'label' | 'inputs' | 'input' | 'separator';\n\nexport enum OtpInputCharset {\n /** Digits only (0-9). Shows a numeric mobile keyboard. */\n Numeric = 'numeric',\n /** Letters and digits. */\n Alphanumeric = 'alphanumeric',\n}\n\n/** Text OtpInput renders of its own, for translating it. */\nexport interface OtpInputLabels {\n /** The group of boxes, used when no `label` is given. */\n field?: string;\n /** One box, given its 1-based position and how many there are. */\n digit?: (position: number, length: number) => string;\n}\n\nexport interface OtpInputProps extends Omit<HtmlProps, 'onChange'> {\n /** Number of character boxes. Default 6. */\n length?: number;\n /** Current code as a plain string, e.g. \"123456\". */\n value?: string;\n /** Fired on every change with the full current code (may be shorter than `length`). */\n onChange?: ((value: string) => void) | null;\n /** Fired once, when the code reaches `length` characters. */\n onComplete?: ((value: string) => void) | null;\n formValidator?: FormValidator | null;\n\n /** Restricts which characters can be typed and picks the mobile keyboard. Default `numeric`. */\n charset?: OtpInputCharset;\n /** Render each box's value as a dot, like a password field. */\n masked?: boolean;\n /** Draw a small gap after these 1-based box indices, e.g. `[3]` to split 6 boxes into 3+3. */\n groupAfter?: number[];\n\n label?: string;\n isValid?: boolean;\n /** Shown in an error Tooltip on focus/hover once `isValid` is `false` (or, with a\n * `formValidator`, once it's touched and has an error). Persists until the value changes\n * `isValid`/`formValidator`'s error state itself — see `clearOnError` to auto-dismiss it. */\n errorMessage?: string;\n isRequired?: boolean;\n /** When an error newly appears (`isValid`/`formValidator` turning invalid), clear every box and\n * refocus the first one after `clearErrorDelay`, so the next attempt starts clean instead of the\n * user editing individual wrong digits (and re-triggering `onComplete` on every keystroke while\n * the code stays at full length). Default `false`. */\n clearOnError?: boolean;\n /** Delay in ms before `clearOnError` clears the boxes, so the wrong code and error message are\n * still visible for a moment first. Default `900`. */\n clearErrorDelay?: number;\n disabled?: boolean;\n /** Focuses the first empty box (or the first box) on mount. */\n autoFocus?: boolean;\n\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<OtpInputSlots>;\n styles?: SlotStyles<OtpInputSlots>;\n /** Overrides the text OtpInput renders of its own. Merged per key. */\n labels?: OtpInputLabels;\n}\n"],"mappings":"AAMA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,QAAA,UAEA,EAAA,aAAA,gBACF,EAAA,CAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"./pagination.module.mjs";import{useState as r}from"react";import i from"classnames";import{faAnglesLeft as a,faAnglesRight as o,faChevronLeft as s,faChevronRight as c}from"@fortawesome/free-solid-svg-icons";import{jsx as l,jsxs as u}from"react/jsx-runtime";var d=`dots`;function f(e,t){return t<e?[]:Array.from({length:t-e+1},(t,n)=>e+n)}function p(e,t){return Math.max(1,Math.min(t,Math.round(e)))}function m(e,t,n,r){if(n*2+r*2+3>=t)return f(1,t);let i=f(1,r),a=f(t-r+1,t),o=i.length>0?[d]:[],s=a.length>0?[d]:[],c=Math.max(e-n,r+1),l=Math.min(e+n,t-r),u=c>r+2,p=l<t-r-1;return!u&&p?[...f(1,r+n*2+2),...s,...a]:u&&!p?[...i,...o,...f(t-r-n*2-1,t)]:[...i,...o,...f(c,l),...s,...a]}function h(f){let{total:h,page:g,defaultPage:_=1,onChange:v=()=>{},siblings:y=1,boundaries:b=1,showControls:x=!0,showEdges:S=!1,disabled:C=!1,previousIcon:w=s,nextIcon:T=c,firstIcon:E=a,lastIcon:D=o,"aria-label":O=`Pagination`,className:k,style:A,classNames:j,styles:M,...N}=e(`Pagination`,f),P=g!==void 0,[F,I]=r(_),L=p(P?g:F,h);if(h<1)return null;function R(e){let t=p(e,h);t!==L&&(P||I(t),v(t))}let z=i(n.paginationControl,j?.control);function B(e,n,r,i,a){return l(`button`,{type:`button`,className:z,style:M?.control,"aria-label":n,disabled:C||a,onClick:()=>R(i),children:t(r)},e)}let V=L<=1,H=L>=h;return u(`nav`,{...N,"aria-label":O,className:i(n.pagination,j?.root,k),style:{...A,...M?.root},children:[S&&B(`first`,`Go to first page`,E,1,V),x&&B(`previous`,`Go to previous page`,w,L-1,V),m(L,h,y,b).map((e,t)=>e===d?l(`span`,{"aria-hidden":`true`,className:i(n.paginationEllipsis,j?.ellipsis),style:M?.ellipsis,children:`…`},`dots-${t}`):l(`button`,{type:`button`,className:i(n.paginationItem,e===L&&n.paginationItemActive,j?.item),style:M?.item,"aria-label":`Go to page ${e}`,"aria-current":e===L?`page`:void 0,disabled:C,onClick:()=>R(e),children:e},e)),x&&B(`next`,`Go to next page`,T,L+1,H),S&&B(`last`,`Go to last page`,D,h,H)]})}export{h as default};
1
+ import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{renderIcon as n}from"../utils/renderIcon.mjs";import r from"./pagination.module.mjs";import{useState as i}from"react";import a from"classnames";import{faAnglesLeft as o,faAnglesRight as s,faChevronLeft as c,faChevronRight as l}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var f=`dots`,p={goToPage:e=>`Go to page ${e}`,first:`Go to first page`,previous:`Go to previous page`,next:`Go to next page`,last:`Go to last page`};function m(e,t){return t<e?[]:Array.from({length:t-e+1},(t,n)=>e+n)}function h(e,t){return Math.max(1,Math.min(t,Math.round(e)))}function g(e,t,n,r){if(n*2+r*2+3>=t)return m(1,t);let i=m(1,r),a=m(t-r+1,t),o=i.length>0?[f]:[],s=a.length>0?[f]:[],c=Math.max(e-n,r+1),l=Math.min(e+n,t-r),u=c>r+2,d=l<t-r-1;return!u&&d?[...m(1,r+n*2+2),...s,...a]:u&&!d?[...i,...o,...m(t-r-n*2-1,t)]:[...i,...o,...m(c,l),...s,...a]}function _(m){let{total:_,page:v,defaultPage:y=1,onChange:b=()=>{},siblings:x=1,boundaries:S=1,showControls:C=!0,showEdges:w=!1,disabled:T=!1,previousIcon:E=c,nextIcon:D=l,firstIcon:O=o,lastIcon:k=s,"aria-label":A=`Pagination`,className:j,style:M,classNames:N,styles:P,labels:F,...I}=e(`Pagination`,m),L=t(`Pagination`,F,p),R=v!==void 0,[z,B]=i(y),V=h(R?v:z,_);if(_<1)return null;function H(e){let t=h(e,_);t!==V&&(R||B(t),b(t))}let U=a(r.paginationControl,N?.control);function W(e,t,r,i,a){return u(`button`,{type:`button`,className:U,style:P?.control,"aria-label":t,disabled:T||a,onClick:()=>H(i),children:n(r)},e)}let G=V<=1,K=V>=_;return d(`nav`,{...I,"aria-label":A,className:a(r.pagination,N?.root,j),style:{...M,...P?.root},children:[w&&W(`first`,L.first,O,1,G),C&&W(`previous`,L.previous,E,V-1,G),g(V,_,x,S).map((e,t)=>e===f?u(`span`,{"aria-hidden":`true`,className:a(r.paginationEllipsis,N?.ellipsis),style:P?.ellipsis,children:`…`},`dots-${t}`):u(`button`,{type:`button`,className:a(r.paginationItem,e===V&&r.paginationItemActive,N?.item),style:P?.item,"aria-label":L.goToPage(e),"aria-current":e===V?`page`:void 0,disabled:T,onClick:()=>H(e),children:e},e)),C&&W(`next`,L.next,D,V+1,K),w&&W(`last`,L.last,k,_,K)]})}export{_ as default};
2
2
  //# sourceMappingURL=pagination.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.mjs","names":[],"sources":["../../../../package/common/pagination/pagination.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { faAnglesLeft, faAnglesRight, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults } from '../configProvider';\nimport type { IconContent } from '../types/icon.types';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { PaginationProps } from './pagination.types';\n\nimport styles from './pagination.module.pcss';\n\nconst DOTS = 'dots';\n\ntype PaginationEntry = number | typeof DOTS;\n\nfunction range(start: number, end: number): number[] {\n if (end < start) return [];\n return Array.from({ length: end - start + 1 }, (_, index) => start + index);\n}\n\nfunction clampPage(page: number, total: number): number {\n return Math.max(1, Math.min(total, Math.round(page)));\n}\n\nfunction getEntries(page: number, total: number, siblings: number, boundaries: number): PaginationEntry[] {\n const maxEntries = siblings * 2 + boundaries * 2 + 3;\n if (maxEntries >= total) return range(1, total);\n\n const leftBoundary = range(1, boundaries);\n const rightBoundary = range(total - boundaries + 1, total);\n const leftGap: PaginationEntry[] = leftBoundary.length > 0 ? [DOTS] : [];\n const rightGap: PaginationEntry[] = rightBoundary.length > 0 ? [DOTS] : [];\n\n const leftSibling = Math.max(page - siblings, boundaries + 1);\n const rightSibling = Math.min(page + siblings, total - boundaries);\n\n const hasLeftDots = leftSibling > boundaries + 2;\n const hasRightDots = rightSibling < total - boundaries - 1;\n\n if (!hasLeftDots && hasRightDots) {\n return [...range(1, boundaries + siblings * 2 + 2), ...rightGap, ...rightBoundary];\n }\n\n if (hasLeftDots && !hasRightDots) {\n return [...leftBoundary, ...leftGap, ...range(total - boundaries - siblings * 2 - 1, total)];\n }\n\n return [...leftBoundary, ...leftGap, ...range(leftSibling, rightSibling), ...rightGap, ...rightBoundary];\n}\n\nfunction Pagination(props: PaginationProps): ReactElement | null {\n const {\n total,\n page: controlledPage,\n defaultPage = 1,\n onChange = () => {},\n siblings = 1,\n boundaries = 1,\n showControls = true,\n showEdges = false,\n disabled = false,\n previousIcon = faChevronLeft,\n nextIcon = faChevronRight,\n firstIcon = faAnglesLeft,\n lastIcon = faAnglesRight,\n 'aria-label': ariaLabel = 'Pagination',\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Pagination', props);\n\n const isControlled = controlledPage !== undefined;\n const [internalPage, setInternalPage] = useState(defaultPage);\n const page = clampPage(isControlled ? controlledPage! : internalPage, total);\n\n if (total < 1) return null;\n\n function goTo(next: number) {\n const clamped = clampPage(next, total);\n if (clamped === page) return;\n if (!isControlled) setInternalPage(clamped);\n onChange(clamped);\n }\n\n const controlClassName = cx(styles.paginationControl, classNames?.control);\n\n function renderControl(key: string, label: string, icon: IconContent, target: number, isDisabled: boolean) {\n return (\n <button\n key={key}\n type='button'\n className={controlClassName}\n style={slotStyles?.control}\n aria-label={label}\n disabled={disabled || isDisabled}\n onClick={() => goTo(target)}\n >\n {renderIcon(icon)}\n </button>\n );\n }\n\n const isFirst = page <= 1;\n const isLast = page >= total;\n\n return (\n <nav\n {...rest}\n aria-label={ariaLabel}\n className={cx(styles.pagination, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {showEdges && renderControl('first', 'Go to first page', firstIcon, 1, isFirst)}\n {showControls && renderControl('previous', 'Go to previous page', previousIcon, page - 1, isFirst)}\n\n {getEntries(page, total, siblings, boundaries).map((entry, index) =>\n entry === DOTS ? (\n <span\n key={`dots-${index}`}\n aria-hidden='true'\n className={cx(styles.paginationEllipsis, classNames?.ellipsis)}\n style={slotStyles?.ellipsis}\n >\n &hellip;\n </span>\n ) : (\n <button\n key={entry}\n type='button'\n className={cx(styles.paginationItem, entry === page && styles.paginationItemActive, classNames?.item)}\n style={slotStyles?.item}\n aria-label={`Go to page ${entry}`}\n aria-current={entry === page ? 'page' : undefined}\n disabled={disabled}\n onClick={() => goTo(entry)}\n >\n {entry}\n </button>\n ),\n )}\n\n {showControls && renderControl('next', 'Go to next page', nextIcon, page + 1, isLast)}\n {showEdges && renderControl('last', 'Go to last page', lastIcon, total, isLast)}\n </nav>\n );\n}\n\nexport default Pagination;\n"],"mappings":"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"}
1
+ {"version":3,"file":"pagination.mjs","names":[],"sources":["../../../../package/common/pagination/pagination.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { faAnglesLeft, faAnglesRight, faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { IconContent } from '../types/icon.types';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { PaginationLabels, PaginationProps } from './pagination.types';\n\nimport styles from './pagination.module.pcss';\n\nconst DOTS = 'dots';\n\ntype PaginationEntry = number | typeof DOTS;\n\nconst DEFAULT_LABELS: Required<PaginationLabels> = {\n goToPage: (page) => `Go to page ${page}`,\n first: 'Go to first page',\n previous: 'Go to previous page',\n next: 'Go to next page',\n last: 'Go to last page',\n};\n\nfunction range(start: number, end: number): number[] {\n if (end < start) return [];\n return Array.from({ length: end - start + 1 }, (_, index) => start + index);\n}\n\nfunction clampPage(page: number, total: number): number {\n return Math.max(1, Math.min(total, Math.round(page)));\n}\n\nfunction getEntries(page: number, total: number, siblings: number, boundaries: number): PaginationEntry[] {\n const maxEntries = siblings * 2 + boundaries * 2 + 3;\n if (maxEntries >= total) return range(1, total);\n\n const leftBoundary = range(1, boundaries);\n const rightBoundary = range(total - boundaries + 1, total);\n const leftGap: PaginationEntry[] = leftBoundary.length > 0 ? [DOTS] : [];\n const rightGap: PaginationEntry[] = rightBoundary.length > 0 ? [DOTS] : [];\n\n const leftSibling = Math.max(page - siblings, boundaries + 1);\n const rightSibling = Math.min(page + siblings, total - boundaries);\n\n const hasLeftDots = leftSibling > boundaries + 2;\n const hasRightDots = rightSibling < total - boundaries - 1;\n\n if (!hasLeftDots && hasRightDots) {\n return [...range(1, boundaries + siblings * 2 + 2), ...rightGap, ...rightBoundary];\n }\n\n if (hasLeftDots && !hasRightDots) {\n return [...leftBoundary, ...leftGap, ...range(total - boundaries - siblings * 2 - 1, total)];\n }\n\n return [...leftBoundary, ...leftGap, ...range(leftSibling, rightSibling), ...rightGap, ...rightBoundary];\n}\n\nfunction Pagination(props: PaginationProps): ReactElement | null {\n const {\n total,\n page: controlledPage,\n defaultPage = 1,\n onChange = () => {},\n siblings = 1,\n boundaries = 1,\n showControls = true,\n showEdges = false,\n disabled = false,\n previousIcon = faChevronLeft,\n nextIcon = faChevronRight,\n firstIcon = faAnglesLeft,\n lastIcon = faAnglesRight,\n 'aria-label': ariaLabel = 'Pagination',\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('Pagination', props);\n const text = useLabels('Pagination', labels, DEFAULT_LABELS);\n\n const isControlled = controlledPage !== undefined;\n const [internalPage, setInternalPage] = useState(defaultPage);\n const page = clampPage(isControlled ? controlledPage! : internalPage, total);\n\n if (total < 1) return null;\n\n function goTo(next: number) {\n const clamped = clampPage(next, total);\n if (clamped === page) return;\n if (!isControlled) setInternalPage(clamped);\n onChange(clamped);\n }\n\n const controlClassName = cx(styles.paginationControl, classNames?.control);\n\n function renderControl(key: string, label: string, icon: IconContent, target: number, isDisabled: boolean) {\n return (\n <button\n key={key}\n type='button'\n className={controlClassName}\n style={slotStyles?.control}\n aria-label={label}\n disabled={disabled || isDisabled}\n onClick={() => goTo(target)}\n >\n {renderIcon(icon)}\n </button>\n );\n }\n\n const isFirst = page <= 1;\n const isLast = page >= total;\n\n return (\n <nav\n {...rest}\n aria-label={ariaLabel}\n className={cx(styles.pagination, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {showEdges && renderControl('first', text.first, firstIcon, 1, isFirst)}\n {showControls && renderControl('previous', text.previous, previousIcon, page - 1, isFirst)}\n\n {getEntries(page, total, siblings, boundaries).map((entry, index) =>\n entry === DOTS ? (\n <span\n key={`dots-${index}`}\n aria-hidden='true'\n className={cx(styles.paginationEllipsis, classNames?.ellipsis)}\n style={slotStyles?.ellipsis}\n >\n &hellip;\n </span>\n ) : (\n <button\n key={entry}\n type='button'\n className={cx(styles.paginationItem, entry === page && styles.paginationItemActive, classNames?.item)}\n style={slotStyles?.item}\n aria-label={text.goToPage(entry)}\n aria-current={entry === page ? 'page' : undefined}\n disabled={disabled}\n onClick={() => goTo(entry)}\n >\n {entry}\n </button>\n ),\n )}\n\n {showControls && renderControl('next', text.next, nextIcon, page + 1, isLast)}\n {showEdges && renderControl('last', text.last, lastIcon, total, isLast)}\n </nav>\n );\n}\n\nexport default Pagination;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import e from"./progressBar.module.mjs";import t from"classnames";import{jsx as n}from"react/jsx-runtime";function r(e){let t=e.replace(`#`,``),n=parseInt(t.substring(0,2),16),r=parseInt(t.substring(2,4),16),i=parseInt(t.substring(4,6),16);return(.299*n+.587*r+.114*i)/255>.5?`#000000`:`#ffffff`}function i({className:i=void 0,total:a=100,progress:o=0,style:s=void 0,...c}){function l(){let i=[];return Array.isArray(o)?i.push(...o):typeof o==`object`?i.push(o):i.push({amount:o}),i.map((o,c)=>{let l=a?o.amount/a*100:0;return n(`div`,{className:t(e.progressBarFill,c===i.length-1&&e.progressBarFillEnd,o.class),style:{width:`${l}%`,background:o.color||void 0,...s||{}},title:o.label?`${o.label}: ${o.amount}`:void 0,children:o.label&&n(`div`,{className:e.progressBarLabel,style:o.color?{color:r(o.color)}:{},children:o.label})},c)})}return n(`div`,{...c,className:t(e.progressBar,i),style:s,children:l()})}export{i as default,r as getContrastColor};
1
+ import e from"./progressBar.module.mjs";import t from"classnames";import{jsx as n}from"react/jsx-runtime";function r(e){let t=e.replace(`#`,``),n=parseInt(t.substring(0,2),16),r=parseInt(t.substring(2,4),16),i=parseInt(t.substring(4,6),16);return(.299*n+.587*r+.114*i)/255>.5?`#000000`:`#ffffff`}function i({className:i=void 0,total:a=100,progress:o=0,style:s=void 0,classNames:c,styles:l,...u}){function d(){let i=[];return Array.isArray(o)?i.push(...o):typeof o==`object`?i.push(o):i.push({amount:o}),i.map((o,s)=>{let u=a?o.amount/a*100:0;return n(`div`,{className:t(e.progressBarFill,s===i.length-1&&e.progressBarFillEnd,o.class,c?.fill),style:{width:`${u}%`,background:o.color||void 0,...l?.fill},title:o.label?`${o.label}: ${o.amount}`:void 0,children:o.label&&n(`div`,{className:t(e.progressBarLabel,c?.label),style:{...o.color?{color:r(o.color)}:{},...l?.label},children:o.label})},s)})}return n(`div`,{...u,className:t(e.progressBar,i,c?.root),style:{...s,...l?.root},children:d()})}export{i as default,r as getContrastColor};
2
2
  //# sourceMappingURL=progressBar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"progressBar.mjs","names":[],"sources":["../../../../package/common/progressBar/progressBar.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { Progress, ProgressBarProps } from './progressBar.types';\n\nimport styles from './progressBar.module.pcss';\n\nexport function getContrastColor(hexColor: string): string {\n const hex = hexColor.replace('#', '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n return luminance > 0.5 ? '#000000' : '#ffffff';\n}\n\nfunction ProgressBar({\n className = undefined,\n total = 100,\n progress = 0,\n style = undefined,\n ...rest\n}: ProgressBarProps): ReactElement {\n function renderProgressBars() {\n const progressArray: Progress[] = [];\n\n if (Array.isArray(progress)) progressArray.push(...progress);\n else if (typeof progress === 'object') progressArray.push(progress);\n else progressArray.push({ amount: progress });\n\n return progressArray.map((prog, index) => {\n const widthPercentage = !total ? 0 : (prog.amount / total) * 100;\n\n return (\n <div\n key={index}\n className={cx(\n styles.progressBarFill,\n index === progressArray.length - 1 && styles.progressBarFillEnd,\n prog.class,\n )}\n style={{\n width: `${widthPercentage}%`,\n background: prog.color || undefined,\n ...(style || {}),\n }}\n title={prog.label ? `${prog.label}: ${prog.amount}` : undefined}\n >\n {prog.label && (\n <div className={styles.progressBarLabel} style={prog.color ? { color: getContrastColor(prog.color) } : {}}>\n {prog.label}\n </div>\n )}\n </div>\n );\n });\n }\n\n return (\n <div {...rest} className={cx(styles.progressBar, className)} style={style}>\n {renderProgressBars()}\n </div>\n );\n}\n\nexport default ProgressBar;\n"],"mappings":"0GAMA,SAAgB,EAAiB,EAA0B,CACzD,IAAM,EAAM,EAAS,QAAQ,IAAK,EAAE,EAC9B,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EAG1C,OADmB,KAAQ,EAAI,KAAQ,EAAI,KAAQ,GAAK,IACrC,GAAM,UAAY,SACvC,CAEA,SAAS,EAAY,CACnB,YAAY,IAAA,GACZ,QAAQ,IACR,WAAW,EACX,QAAQ,IAAA,GACR,GAAG,GAC8B,CACjC,SAAS,GAAqB,CAC5B,IAAM,EAA4B,CAAC,EAMnC,OAJI,MAAM,QAAQ,CAAQ,EAAG,EAAc,KAAK,GAAG,CAAQ,EAClD,OAAO,GAAa,SAAU,EAAc,KAAK,CAAQ,EAC7D,EAAc,KAAK,CAAE,OAAQ,CAAS,CAAC,EAErC,EAAc,KAAK,EAAM,IAAU,CACxC,IAAM,EAAmB,EAAa,EAAK,OAAS,EAAS,IAA5B,EAEjC,OACE,EAAC,MAAD,CAEE,UAAW,EACT,EAAO,gBACP,IAAU,EAAc,OAAS,GAAK,EAAO,mBAC7C,EAAK,KACP,EACA,MAAO,CACL,MAAO,GAAG,EAAgB,GAC1B,WAAY,EAAK,OAAS,IAAA,GAC1B,GAAI,GAAS,CAAC,CAChB,EACA,MAAO,EAAK,MAAQ,GAAG,EAAK,MAAM,IAAI,EAAK,SAAW,IAAA,GAErD,SAAA,EAAK,OACJ,EAAC,MAAD,CAAK,UAAW,EAAO,iBAAkB,MAAO,EAAK,MAAQ,CAAE,MAAO,EAAiB,EAAK,KAAK,CAAE,EAAI,CAAC,EACrG,SAAA,EAAK,KACH,CAAA,CAEJ,EAlBE,CAkBF,CAET,CAAC,CACH,CAEA,OACE,EAAC,MAAD,CAAK,GAAI,EAAM,UAAW,EAAG,EAAO,YAAa,CAAS,EAAU,QACjE,SAAA,EAAmB,CACjB,CAAA,CAET"}
1
+ {"version":3,"file":"progressBar.mjs","names":[],"sources":["../../../../package/common/progressBar/progressBar.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport cx from 'classnames';\nimport { Progress, ProgressBarProps } from './progressBar.types';\n\nimport styles from './progressBar.module.pcss';\n\nexport function getContrastColor(hexColor: string): string {\n const hex = hexColor.replace('#', '');\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n return luminance > 0.5 ? '#000000' : '#ffffff';\n}\n\nfunction ProgressBar({\n className = undefined,\n total = 100,\n progress = 0,\n style = undefined,\n classNames,\n styles: slotStyles,\n ...rest\n}: ProgressBarProps): ReactElement {\n function renderProgressBars() {\n const progressArray: Progress[] = [];\n\n if (Array.isArray(progress)) progressArray.push(...progress);\n else if (typeof progress === 'object') progressArray.push(progress);\n else progressArray.push({ amount: progress });\n\n return progressArray.map((prog, index) => {\n const widthPercentage = !total ? 0 : (prog.amount / total) * 100;\n\n return (\n <div\n key={index}\n className={cx(\n styles.progressBarFill,\n index === progressArray.length - 1 && styles.progressBarFillEnd,\n prog.class,\n classNames?.fill,\n )}\n style={{\n width: `${widthPercentage}%`,\n background: prog.color || undefined,\n ...slotStyles?.fill,\n }}\n title={prog.label ? `${prog.label}: ${prog.amount}` : undefined}\n >\n {prog.label && (\n <div\n className={cx(styles.progressBarLabel, classNames?.label)}\n style={{ ...(prog.color ? { color: getContrastColor(prog.color) } : {}), ...slotStyles?.label }}\n >\n {prog.label}\n </div>\n )}\n </div>\n );\n });\n }\n\n return (\n <div\n {...rest}\n className={cx(styles.progressBar, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {renderProgressBars()}\n </div>\n );\n}\n\nexport default ProgressBar;\n"],"mappings":"0GAMA,SAAgB,EAAiB,EAA0B,CACzD,IAAM,EAAM,EAAS,QAAQ,IAAK,EAAE,EAC9B,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EACpC,EAAI,SAAS,EAAI,UAAU,EAAG,CAAC,EAAG,EAAE,EAG1C,OADmB,KAAQ,EAAI,KAAQ,EAAI,KAAQ,GAAK,IACrC,GAAM,UAAY,SACvC,CAEA,SAAS,EAAY,CACnB,YAAY,IAAA,GACZ,QAAQ,IACR,WAAW,EACX,QAAQ,IAAA,GACR,aACA,OAAQ,EACR,GAAG,GAC8B,CACjC,SAAS,GAAqB,CAC5B,IAAM,EAA4B,CAAC,EAMnC,OAJI,MAAM,QAAQ,CAAQ,EAAG,EAAc,KAAK,GAAG,CAAQ,EAClD,OAAO,GAAa,SAAU,EAAc,KAAK,CAAQ,EAC7D,EAAc,KAAK,CAAE,OAAQ,CAAS,CAAC,EAErC,EAAc,KAAK,EAAM,IAAU,CACxC,IAAM,EAAmB,EAAa,EAAK,OAAS,EAAS,IAA5B,EAEjC,OACE,EAAC,MAAD,CAEE,UAAW,EACT,EAAO,gBACP,IAAU,EAAc,OAAS,GAAK,EAAO,mBAC7C,EAAK,MACL,GAAY,IACd,EACA,MAAO,CACL,MAAO,GAAG,EAAgB,GAC1B,WAAY,EAAK,OAAS,IAAA,GAC1B,GAAG,GAAY,IACjB,EACA,MAAO,EAAK,MAAQ,GAAG,EAAK,MAAM,IAAI,EAAK,SAAW,IAAA,GAErD,SAAA,EAAK,OACJ,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,iBAAkB,GAAY,KAAK,EACxD,MAAO,CAAE,GAAI,EAAK,MAAQ,CAAE,MAAO,EAAiB,EAAK,KAAK,CAAE,EAAI,CAAC,EAAI,GAAG,GAAY,KAAM,EAE7F,SAAA,EAAK,KACH,CAAA,CAEJ,EAtBE,CAsBF,CAET,CAAC,CACH,CAEA,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,YAAa,EAAW,GAAY,IAAI,EAC7D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAEtC,SAAA,EAAmB,CACjB,CAAA,CAET"}
@@ -1,2 +1,2 @@
1
- import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"../actionIcon/actionIcon.mjs";import r from"../hooks/useCoarsePointer.mjs";import i from"../input/input.mjs";import{OpeningKind as a,WallType as o}from"../floorPlan/floorPlan.types.mjs";import{pointToSegment as s}from"../floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as c,addOpening as l,addRect as ee,addWall as u,detachWall as te,dissolveNode as ne,mergeNodes as re,moveNode as ie,removeOpening as ae,removeWall as oe,splitWall as se,updateOpening as ce,weldShortWalls as le}from"../floorPlan/floorPlan.graph.mjs";import{addFloor as ue,duplicateFloor as de,emptyFloorPlan as fe,floorBelow as pe,floorBounds as me,floorIndex as he,getFloor as ge,moveFloor as _e,removeFloor as ve,renameFloor as ye,setFloor as be,setFloorHeight as xe}from"../floorPlan/floorPlan.plan.mjs";import{commitDerivation as Se,derivePlan as Ce}from"../floorPlan/floorPlan.rooms.mjs";import{HIT_PX as we,HIT_PX_COARSE as Te,hitTest as Ee,selectionsEqual as De,worldTolerances as d}from"../floorPlan/floorPlan.hit.mjs";import{SnapKind as f,clientToWorld as Oe,resolveSnap as ke}from"../floorPlan/floorPlan.snap.mjs";import{planFromJson as Ae,planToJson as je}from"../floorPlan/floorPlan.json.mjs";import Me from"../numberInput/index.mjs";import Ne from"../planCanvas/planCanvas.mjs";import{usePlanHistory as Pe}from"./usePlanHistory.mjs";import p from"./roomDrawer.module.mjs";import{forwardRef as Fe,useCallback as m,useEffect as h,useImperativeHandle as Ie,useMemo as Le,useRef as g,useState as _}from"react";import v from"classnames";import{faAngleDown as Re,faAngleUp as ze,faArrowPointer as Be,faArrowRotateLeft as Ve,faArrowRotateRight as He,faBorderAll as Ue,faClone as We,faDoorOpen as Ge,faDownload as Ke,faDraftingCompass as qe,faExpand as Je,faLayerGroup as Ye,faMagnet as Xe,faMagnifyingGlassMinus as Ze,faMagnifyingGlassPlus as Qe,faMinus as $e,faPlus as et,faRulerCombined as tt,faSquare as nt,faTrash as rt,faUpload as it,faWindowMaximize as at}from"@fortawesome/free-solid-svg-icons";import{Fragment as ot,jsx as y,jsxs as b}from"react/jsx-runtime";var st=[`select`,`wall`,`rect`,`door`,`window`,`archway`,`measure`],ct={v:`select`,w:`wall`,r:`rect`,d:`door`,n:`window`,a:`archway`,m:`measure`},lt={door:a.Door,window:a.Window,archway:a.Archway},ut={[a.Door]:`Door`,[a.Window]:`Window`,[a.Archway]:`Archway`,[a.Gap]:`Gap`},dt={[a.Door]:{width:900,sill:0,head:2100},[a.Window]:{width:1200,sill:900,head:2100},[a.Archway]:{width:1200,sill:0,head:2100},[a.Gap]:{width:1e3,sill:0,head:2500}},ft=1,pt=4,mt=[];function ht(e){return e>=1e3?`${(e/1e3).toFixed(2)} m`:`${Math.round(e)} mm`}function gt(e){let t=e/1e6;return`${t.toFixed(+(t<10))} m²`}function _t(e){let t=e*180/Math.PI;return t=(t%360+360)%360,t>180&&(t-=360),`${Math.abs(t)<.05?0:Math.round(t*10)/10}°`}var x=Fe(function(a,Fe){let{value:x,defaultValue:vt,onChange:S,onChangeEnd:yt,floorId:bt,defaultFloorId:xt,onFloorChange:St,showFloorBar:Ct=!0,showUnderlay:wt=!0,tool:Tt,defaultTool:Et=`select`,onToolChange:Dt,tools:Ot=st,selection:kt,defaultSelection:At,onSelectionChange:jt,multiSelect:Mt=!0,onHoverChange:Nt,view:Pt,defaultView:Ft,onViewChange:It,minZoom:Lt=.005,maxZoom:Rt=2,fitOnMount:zt=!0,gridSize:C=100,showGrid:Bt=!0,snap:Vt=!0,angleLock:Ht=!1,constrainAngle:Ut=45,showSnapGuides:Wt=!0,wallThickness:Gt=c.thickness,wallHeight:Kt,openingDefaults:qt,showMeasurements:Jt=!0,formatLength:Yt=ht,formatArea:Xt=gt,showToolbar:Zt=!0,showInspector:Qt=!0,showHint:$t=!0,showHistoryControls:en=!0,showFileControls:tn=!0,fileName:nn,onImport:rn,historyMode:an=`internal`,historyLimit:on=50,onHistoryChange:sn,readOnly:cn=!1,disabled:w=!1,canvasHeight:ln=`420px`,getRoomColor:un,renderRoomLabel:dn,labels:T,icons:E,"aria-label":fn,className:pn,style:mn,classNames:D,styles:O,...hn}=e(`RoomDrawer`,a),gn=r(),k=gn?Te:we,_n=g(null),vn=g(null),yn=g(null),bn=g(null),A=g({kind:`none`}),xn=g(new Map),Sn=g(null),Cn=g(!1),wn=g(!1),Tn=g(!1),En=Le(()=>vt??x??fe(),[]),j=Pe(En,on),Dn=x!==void 0,M=Dn?x:j.present;h(()=>{if(Dn&&x){if(x===bn.current){j.replace(x);return}j.commit(x,`external`)}},[x,Dn]);let[On,kn]=_(xt),An=bt??On??M.floors[0]?.id,N=Le(()=>ge(M,An)??ge(M)??fe().floors[0],[M,An]),[jn,Mn]=_(wt);h(()=>Mn(wt),[wt]);let Nn=Le(()=>jn?pe(M,N.id):null,[jn,M,N.id]),Pn=m(e=>{e!==N.id&&(bt===void 0&&kn(e),St?.(e))},[N.id,bt,St]),P=Le(()=>Ce(N),[N]).rooms,[Fn,In]=_(Et),F=Tt??Fn,Ln=m(e=>{Tt===void 0&&In(e),Dt?.(e)},[Tt,Dt]),[Rn,zn]=_(At??mt),I=kt===void 0?Rn:kt,L=g(I);L.current=I;let R=m(e=>{let t=e===null?mt:Array.isArray(e)?e:[e];L.current=t,kt===void 0&&zn(t),jt?.([...t])},[kt,jt]),Bn=m(e=>{let t=L.current,n=t.filter(t=>t.type!==e.type||t.id!==e.id);R(n.length===t.length?[...t,e]:n)},[R]),z=I.length===1?I[0]:null,Vn=m(e=>{let t=new Set;for(let n of e)if(n.type===`node`)t.add(n.id);else if(n.type===`wall`){let e=N.walls[n.id];e&&(t.add(e.a),t.add(e.b))}else if(n.type===`room`){let e=P.find(e=>e.roomId===n.id);for(let n of e?.nodeIds??[])t.add(n)}return t},[N.walls,P]),Hn=Le(()=>Vn(I),[Vn,I]),[Un,Wn]=_(null),[Gn,Kn]=_(Ft??{x:0,y:0,zoom:.05}),B=Pt??Gn,V=m(e=>{Pt===void 0&&Kn(e),It?.(e)},[Pt,It]),[H,qn]=_({width:800,height:420}),[U,Jn]=_([]),[W,Yn]=_(null),[Xn,Zn]=_(Vt),[Qn,$n]=_(Ht);h(()=>Zn(Vt),[Vt]),h(()=>$n(Ht),[Ht]);let[er,tr]=_(Bt);h(()=>tr(Bt),[Bt]);let nr=g(null),[G,rr]=_(null),[K,ir]=_([]),ar=g(0),[or,sr]=_(null),cr=g(null),lr=m(e=>{let t=d(k,B.zoom);for(let n=K.length-1;n>=0;n--){let r=K[n];if(Math.hypot(e.x-r.a.x,e.y-r.a.y)<=t.node)return{id:r.id,end:`a`};if(Math.hypot(e.x-r.b.x,e.y-r.b.y)<=t.node)return{id:r.id,end:`b`}}for(let n=K.length-1;n>=0;n--){let r=K[n];if(s(e,r.a,r.b).dist<=t.wall)return{id:r.id}}return null},[K,k,B.zoom]),[ur,dr]=_(null),q=!cn&&!w,fr=Le(()=>{if(U.length<2)return;let e=U[U.length-2],t=U[U.length-1];return Math.atan2(t.y-e.y,t.x-e.x)},[U]);h(()=>{let e=vn.current;if(!e)return;let t=new ResizeObserver(()=>{let t=e.getBoundingClientRect();t.width>0&&t.height>0&&qn({width:Math.round(t.width),height:Math.round(t.height)})});t.observe(e);let n=e.getBoundingClientRect();return n.width>0&&n.height>0&&qn({width:Math.round(n.width),height:Math.round(n.height)}),()=>t.disconnect()},[]);let pr=m((e,t)=>{let n=vn.current?.getBoundingClientRect()??{left:0,top:0};return Oe(e,t,n,B)},[B]),J=m(e=>({x:(e.x-B.x)*B.zoom,y:(e.y-B.y)*B.zoom}),[B]),Y=m((e,t,n,r,i)=>{let a=Xn!==wn.current,o=Qn!==Tn.current,s=ke(e,{floor:N,pxToWorld:B.zoom>0?1/B.zoom:1,origin:t,referenceAngle:r,excludeNodeIds:n,excludeWallIds:i,options:{enabled:a?[f.Node,f.Intersection,f.Wall,f.Angle,f.Extension,f.Alignment,f.Grid]:[],gridSize:C,angleStepDeg:o?Ut:0,toleranceScreenPx:gn?16:10}});return nr.current=s,s},[N,B.zoom,Xn,Qn,C,Ut,gn]),mr=m(e=>{let t=Object.values(N.walls).filter(t=>t.a===e||t.b===e),n=new Set(t.map(e=>e.id)),r=N.nodes[e];if(!r)return{excludeWallIds:n};let i={x:r.x,y:r.y},a,o=t[0];if(o){let t=o.a===e?o.b:o.a,n=N.nodes[t];n&&(a=Math.atan2(n.y-r.y,n.x-r.x))}return{origin:i,referenceAngle:a,excludeWallIds:n}},[N]),hr=m((e={})=>{let t=e.padding??24,n=me(N);if(!n||n.width<=0||n.height<=0){V({x:-1e3,y:-1e3,zoom:.05});return}let r=Math.min((H.width-t*2)/n.width,(H.height-t*2)/n.height),i=Math.max(Lt,Math.min(Rt,r));V({x:n.minX-(H.width/i-n.width)/2,y:n.minY-(H.height/i-n.height)/2,zoom:i})},[N,H.width,H.height,Lt,Rt,V]),gr=g(!1);h(()=>{zt&&!gr.current&&Object.keys(N.nodes).length!==0&&(H.width<=1||(gr.current=!0,hr()))},[zt,N,H.width,hr]);let _r=m((e,t,n,r=[],i={})=>{if(e===N)return M;let a=be(M,e);bn.current=a,n?i.push===!1?j.replace(a):j.commit(a,t,r):j.updateGesture(a);let o={reason:t,committed:n,targetIds:r};return S?.(a,o),n&&yt?.(a,o),a},[N,M,j,S,yt]),X=m((e,t,n=[],r={})=>{let i=Se(le(e).floor).floor;return _r(i,t,!0,n,r)},[_r]);h(()=>{sn?.({canUndo:j.canUndo,canRedo:j.canRedo})},[j.canUndo,j.canRedo,sn]);let vr=Le(()=>z?.type===`room`?P.find(e=>e.roomId===z.id)??null:null,[z,P]),Z=z?.type===`wall`?N.walls[z.id]:void 0,yr=z?.type===`opening`?N.openings[z.id]:void 0,br=Le(()=>{if(!Z)return null;let e=N.nodes[Z.a],t=N.nodes[Z.b];return!e||!t?null:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}},[Z,N.nodes]),xr=m(()=>{if(!q||!Z)return;let e=se(N,Z.id,.5);e.result.wallIds&&(X(e.floor,`edit-wall`,[e.result.nodeId]),R({type:`node`,id:e.result.nodeId}))},[q,Z,N,X,R]),Sr=m((e,t,n=new Set)=>{if(e.type===`wall`)return{floor:oe(t,e.id).floor};if(e.type===`opening`)return{floor:ae(t,e.id).floor};if(e.type===`node`){let n=ne(t,e.id,{force:!0});if(n.result)return{floor:n.floor,reselect:{type:`wall`,id:n.result.wallId}};let r=t;for(let n of Object.values(t.walls))(n.a===e.id||n.b===e.id)&&(r=oe(r,n.id,{dissolveCollinear:!1}).floor);return{floor:r}}let r=P.find(t=>t.roomId===e.id);if(!r)return{floor:t};let i=new Set;for(let t of P)if(t.roomId!==e.id&&!(t.roomId&&n.has(t.roomId)))for(let e of t.wallIds)i.add(e);let a=t;for(let e of new Set(r.wallIds))i.has(e)||(a=oe(a,e,{dissolveCollinear:!1}).floor);let o={...a.rooms};return delete o[e.id],{floor:{...a,rooms:o}}},[P]),Cr=m(()=>{let e=L.current;if(!q||e.length===0)return;let t={room:0,opening:1,wall:2,node:3},n=[...e].sort((e,n)=>t[e.type]-t[n.type]),r=new Set(n.filter(e=>e.type===`room`).map(e=>e.id)),i=N,a;for(let e of n){let t=Sr(e,i,r);i=t.floor,n.length===1&&(a=t.reselect)}i!==N&&(X(i,`delete`,n.map(e=>e.id)),R(a??null))},[q,N,Sr,X,R]),wr=m(()=>{Jn(e=>e.length===0?e:[]),rr(null)},[]);h(()=>{wr()},[F,wr]);let Tr=m(e=>{if(w)return;if(_n.current?.focus(),dr(null),xn.current.set(e.pointerId,{x:e.clientX,y:e.clientY}),e.currentTarget.setPointerCapture?.(e.pointerId),xn.current.size===2){let[e,t]=[...xn.current.values()];A.current.kind!==`none`&&A.current.kind!==`pan`&&j.cancelGesture(),A.current={kind:`pinch`,startDist:Math.hypot(t.x-e.x,t.y-e.y),startView:B,startMid:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}};return}if(xn.current.size>2)return;if(Sn.current={client:{x:e.clientX,y:e.clientY},moved:!1},e.button===1||Cn.current){A.current={kind:`pan`,startClient:{x:e.clientX,y:e.clientY},startView:B};return}if(e.button!==0)return;let t=pr(e.clientX,e.clientY);if(!q){let e=Ee(N,P,t,d(k,B.zoom));R(e);return}if(F===`rect`){let e=Y(t).point;A.current={kind:`rect`,start:e,current:e},j.beginGesture();return}if(F===`measure`){let e=lr(t);if(e){let n=K.find(t=>t.id===e.id);A.current=e.end?{kind:`measureEnd`,id:e.id,end:e.end}:{kind:`measureMove`,id:e.id,startWorld:t,origA:n.a,origB:n.b};return}let n=Y(t).point;A.current={kind:`measure`,start:n,current:n};return}if(F===`wall`){let e=U[U.length-1],n=Y(t,e,void 0,fr).point;if(U.length===0){Jn([n]);return}let r=U[U.length-1],i=u(N,r,n,{thickness:Gt,type:o.Interior,height:Kt},d(k,B.zoom).node);i.result.wallIds.length>0&&X(i.floor,`draw-wall`,i.result.wallIds),U.length>=2&&Math.hypot(n.x-U[0].x,n.y-U[0].y)<d(k,B.zoom).node?wr():Jn(e=>[...e,n]);return}let n=lt[F];if(n){let e=d(k,B.zoom),r=Ee(N,P,t,e,{accept:[`wall`]});if(r?.type!==`wall`)return;let i=N.walls[r.id],a=N.nodes[i.a],o=N.nodes[i.b],s=Math.hypot(o.x-a.x,o.y-a.y),c=((t.x-a.x)*(o.x-a.x)+(t.y-a.y)*(o.y-a.y))/(s*s||1),ee={...dt[n],...qt?.[n]},u=l(N,{wallId:i.id,kind:n,offset:Math.min(Math.max(c,0),1)*s,width:ee.width,sill:ee.sill,head:ee.head});u.result.openingId&&(X(u.floor,`add-opening`,[u.result.openingId]),R({type:`opening`,id:u.result.openingId}));return}let r=d(k,B.zoom);if(br&&z?.type===`wall`&&Math.hypot(t.x-br.x,t.y-br.y)<=r.node){j.beginGesture(),A.current={kind:`wallSplit`,wallId:z.id,at:br};return}let i=Ee(N,P,t,r),a=Mt&&(e.ctrlKey||e.metaKey);if(!i){a||R(null),A.current=Mt?{kind:`marquee`,start:t,current:t,additive:a,base:L.current}:{kind:`none`};return}if((e.ctrlKey||e.metaKey)&&i.type===`wall`&&N.walls[i.id]){let e=N.walls[i.id];a||R(i),j.beginGesture(),A.current={kind:`wall`,wallId:i.id,startWorld:t,origA:{...N.nodes[e.a]},origB:{...N.nodes[e.b]},moved:!1,detach:!0,toggle:a};return}if(a){Bn(i),A.current={kind:`none`};return}if(L.current.some(e=>e.type===i.type&&e.id===i.id)||R(i),j.beginGesture(),L.current.length>1){let e=[...Vn(L.current)],n={};for(let t of e){let e=N.nodes[t];e&&(n[t]={x:e.x,y:e.y})}A.current={kind:`room`,nodeIds:e,startWorld:t,orig:n,moved:!1};return}if(i.type===`node`)A.current={kind:`node`,nodeId:i.id,moved:!1,...mr(i.id)};else if(i.type===`wall`){let e=N.walls[i.id];A.current={kind:`wall`,wallId:i.id,startWorld:t,origA:{...N.nodes[e.a]},origB:{...N.nodes[e.b]},moved:!1}}else if(i.type===`opening`)A.current={kind:`opening`,openingId:i.id,moved:!1};else{let e=P.find(e=>e.roomId===i.id),n=e?[...new Set(e.nodeIds)]:[],r={};for(let e of n){let t=N.nodes[e];t&&(r[e]={x:t.x,y:t.y})}A.current={kind:`room`,nodeIds:n,startWorld:t,orig:r,moved:!1}}},[w,q,B,F,N,P,k,pr,Y,U,Gt,Kt,qt,X,R,br,z,fr,mr,Vn,Mt,Bn,j,wr,lr,K]),Er=m(e=>{if(w)return;xn.current.has(e.pointerId)&&xn.current.set(e.pointerId,{x:e.clientX,y:e.clientY});let t=A.current;if(t.kind===`pinch`&&xn.current.size>=2){let[e,n]=[...xn.current.values()],r=Math.hypot(n.x-e.x,n.y-e.y);if(t.startDist<=0)return;let i=Math.max(Lt,Math.min(Rt,t.startView.zoom*(r/t.startDist))),a=vn.current?.getBoundingClientRect()??{left:0,top:0},o={x:(e.x+n.x)/2,y:(e.y+n.y)/2},s=Oe(t.startMid.x,t.startMid.y,a,t.startView);V({x:s.x-(o.x-a.left)/i,y:s.y-(o.y-a.top)/i,zoom:i});return}if(Sn.current){let t=e.clientX-Sn.current.client.x,n=e.clientY-Sn.current.client.y;Math.hypot(t,n)>pt&&(Sn.current.moved=!0)}if(t.kind===`pan`){V({x:t.startView.x-(e.clientX-t.startClient.x)/t.startView.zoom,y:t.startView.y-(e.clientY-t.startClient.y)/t.startView.zoom,zoom:t.startView.zoom});return}let n=pr(e.clientX,e.clientY);if(Yn(n),t.kind===`none`){if(!q)return;if(F===`wall`&&U.length>0){let e=Y(n,U[U.length-1],void 0,fr);Yn(e.point),rr(e);return}if(F===`select`){let e=Ee(N,P,n,d(k,B.zoom));De(e,Un)||(Wn(e),Nt?.(e))}F===`measure`&&sr(lr(n)?.id??null);return}if(Sn.current?.moved){if(t.kind===`measureEnd`){let e=Y(n).point;ir(n=>n.map(n=>n.id===t.id?{...n,[t.end]:e}:n)),Yn(e);return}if(t.kind===`measureMove`){let e=n.x-t.startWorld.x,r=n.y-t.startWorld.y;ir(n=>n.map(n=>n.id===t.id?{...n,a:{x:t.origA.x+e,y:t.origA.y+r},b:{x:t.origB.x+e,y:t.origB.y+r}}:n));return}if(t.kind===`rect`||t.kind===`measure`){A.current={...t,current:Y(n).point},Yn(Y(n).point);return}if(t.kind===`marquee`){A.current={...t,current:n},Yn(n);return}if(t.kind===`wallSplit`){let e=se(N,t.wallId,t.at);if(!e.result.wallIds){A.current={kind:`none`};return}let r=e.result.nodeId,i=N.walls[t.wallId],a=i?e.floor.nodes[i.a]:void 0,o=i?e.floor.nodes[i.b]:void 0,s={origin:a?{x:a.x,y:a.y}:void 0,referenceAngle:a&&o?Math.atan2(o.y-a.y,o.x-a.x):void 0,excludeWallIds:new Set(e.result.wallIds)},c=Y(n,s.origin,new Set([r]),s.referenceAngle,s.excludeWallIds).point;A.current={kind:`node`,nodeId:r,moved:!0,...s},R({type:`node`,id:r}),rr(nr.current),_r(ie(e.floor,r,c).floor,`move-node`,!1,[r]);return}if(t.kind===`node`){let e=Y(n,t.origin,new Set([t.nodeId]),t.referenceAngle,t.excludeWallIds).point;rr(nr.current),A.current={...t,moved:!0},_r(ie(N,t.nodeId,e).floor,`move-node`,!1,[t.nodeId]);return}if(t.kind===`wall`){let e=N.walls[t.wallId];if(!e)return;let r=t.origB.x-t.origA.x,i=t.origB.y-t.origA.y,a=Math.hypot(r,i);if(a<1e-6)return;let o={x:-i/a,y:r/a},s=(n.x-t.startWorld.x)*o.x+(n.y-t.startWorld.y)*o.y,c=Vt!==wn.current&&C>0?C:1,l=Math.round(s/c)*c,ee=Math.max(c,10);if(t.detach){if(Math.abs(l)<ee)return;let e=te(N,t.wallId,{x:o.x*l,y:o.y*l});if(!e.result)return;A.current={...t,detach:!1,toggle:!1,detachedSign:Math.sign(l),moved:!0},R({type:`wall`,id:t.wallId}),_r(e.floor,`move-wall`,!1,[t.wallId]);return}let u=ie(N,e.a,{x:t.origA.x+o.x*l,y:t.origA.y+o.y*l}).floor;u=ie(u,e.b,{x:t.origB.x+o.x*l,y:t.origB.y+o.y*l}).floor,t.detachedSign&&Math.abs(l)<10?(u=le(u).floor,A.current={...t,detachedSign:void 0,moved:!0}):A.current={...t,moved:!0},_r(u,`move-wall`,!1,[t.wallId]);return}if(t.kind===`opening`){let e=N.openings[t.openingId];if(!e)return;let r=N.walls[e.wallId],i=N.nodes[r.a],a=N.nodes[r.b],o=Math.hypot(a.x-i.x,a.y-i.y),s=((n.x-i.x)*(a.x-i.x)+(n.y-i.y)*(a.y-i.y))/(o*o||1);A.current={...t,moved:!0},_r(ce(N,t.openingId,{offset:Math.min(Math.max(s,0),1)*o}).floor,`move-opening`,!1,[t.openingId]);return}if(t.kind===`room`){let e=n.x-t.startWorld.x,r=n.y-t.startWorld.y,i=Vt!==wn.current&&C>0?C:1,a=Math.round(e/i)*i,o=Math.round(r/i)*i,s=N;for(let e of t.nodeIds){let n=t.orig[e];n&&(s=ie(s,e,{x:n.x+a,y:n.y+o}).floor)}A.current={...t,moved:!0},_r(s,`move-room`,!1,t.nodeIds)}}},[w,q,F,N,P,Un,k,B.zoom,Lt,Rt,C,Vt,pr,Y,_r,V,R,U,fr,Nt,lr]),Dr=m((e,t)=>{xn.current.delete(e.pointerId);let n=A.current;A.current={kind:`none`};let r=Sn.current?.moved??!1;if(Sn.current=null,rr(null),n.kind===`none`||n.kind===`pan`||n.kind===`pinch`)return;if(n.kind===`marquee`){if(t||!r){t&&R([...n.base]);return}let e=Math.min(n.start.x,n.current.x),i=Math.max(n.start.x,n.current.x),a=Math.min(n.start.y,n.current.y),o=Math.max(n.start.y,n.current.y),s=[];for(let t of Object.values(N.nodes))t.x>=e&&t.x<=i&&t.y>=a&&t.y<=o&&s.push({type:`node`,id:t.id});if(n.additive){let e=new Set(n.base.map(e=>`${e.type}:${e.id}`));R([...n.base,...s.filter(t=>!e.has(`${t.type}:${t.id}`))])}else R(s);return}if(t){let e=j.cancelGesture();e&&S?.(e,{reason:`external`,committed:!1,targetIds:[]});return}if(n.kind===`measureEnd`||n.kind===`measureMove`)return;if(n.kind===`measure`){let e=Math.hypot(n.current.x-n.start.x,n.current.y-n.start.y);r&&e>ft&&(ar.current+=1,ir(e=>[...e,{id:ar.current,a:n.start,b:n.current}]));return}if(n.kind===`rect`){if(!r){j.cancelGesture();return}let e=ee(N,n.start,n.current,{thickness:Gt,type:o.Interior,height:Kt},d(k,B.zoom).node);if(e.result.wallIds.length===0){j.cancelGesture();return}let t=j.endGesture();X(e.floor,`draw-rect`,e.result.wallIds,{push:!t});return}if(!r){j.cancelGesture(),n.kind===`wall`&&n.toggle&&Bn({type:`wall`,id:n.wallId});return}if(n.kind===`node`){let e=N.nodes[n.nodeId];if(e){let t=d(k,B.zoom).node,r=Object.values(N.nodes).find(r=>r.id!==n.nodeId&&Math.hypot(r.x-e.x,r.y-e.y)<=t);if(r){let e=j.endGesture();X(re(N,r.id,n.nodeId).floor,`move-node`,[r.id],{push:!e}),R({type:`node`,id:r.id});return}}}let i=j.endGesture(),a=n.kind===`wall`?`move-wall`:n.kind===`opening`?`move-opening`:n.kind===`room`?`move-room`:`move-node`;X(N,a,[],{push:!i})},[N,j,k,B.zoom,Gt,Kt,X,R,Bn,S]);h(()=>{let e=vn.current;if(!e||w)return;function t(t){t.preventDefault();let n=e.getBoundingClientRect(),r=Math.exp(-t.deltaY*.002);V((()=>{let e=Or.current,i=Math.max(Lt,Math.min(Rt,e.zoom*r)),a=Oe(t.clientX,t.clientY,n,e);return{x:a.x-(t.clientX-n.left)/i,y:a.y-(t.clientY-n.top)/i,zoom:i}})())}return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[w,Lt,Rt,V]);let Or=g(B);Or.current=B;let kr=m(e=>{let t=Math.max(Lt,Math.min(Rt,B.zoom*e)),n={x:B.x+H.width/2/B.zoom,y:B.y+H.height/2/B.zoom};V({x:n.x-H.width/2/t,y:n.y-H.height/2/t,zoom:t})},[B,H,Lt,Rt,V]),Ar=m(()=>{if(an===`none`)return;let e=j.undo();e&&(bn.current=e,S?.(e,{reason:`undo`,committed:!0,targetIds:[]}),yt?.(e,{reason:`undo`,committed:!0,targetIds:[]}))},[an,j,S,yt]),jr=m(()=>{if(an===`none`)return;let e=j.redo();e&&(bn.current=e,S?.(e,{reason:`redo`,committed:!0,targetIds:[]}),yt?.(e,{reason:`redo`,committed:!0,targetIds:[]}))},[an,j,S,yt]),Mr=m(()=>{let e=P.filter(e=>e.roomId).map(e=>({type:`room`,id:e.roomId}));if(e.length>0){R(e);return}R(Object.keys(N.nodes).map(e=>({type:`node`,id:e})))},[P,N.nodes,R]),Nr=m((e,t)=>{if(!q||Hn.size===0)return;let n=C>0?C:100,r=Tn.current?n*10:n,i=N;for(let n of Hn){let a=i.nodes[n];a&&(i=ie(i,n,{x:a.x+e*r,y:a.y+t*r}).floor)}X(i,`nudge`,[...Hn])},[q,Hn,N,C,X]),Pr=m(e=>{if(w)return;let t=e.target;if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement){e.key===`Escape`&&t.blur();return}if(e.key===`Shift`&&(Tn.current=!0),e.key===`Alt`&&(wn.current=!0),e.key===` `&&!Cn.current){Cn.current=!0,e.preventDefault();return}let n=e.metaKey||e.ctrlKey;if(n&&e.key.toLowerCase()===`z`){e.preventDefault(),e.shiftKey?jr():Ar();return}if(n&&e.key.toLowerCase()===`a`){e.preventDefault(),Mt&&Mr();return}if(n&&e.key.toLowerCase()===`y`){e.preventDefault(),jr();return}if(e.key===`Escape`){U.length>0?wr():K.length>0?ir([]):R(null);return}if(e.key===`Enter`&&F===`wall`){wr();return}if(e.key===`Delete`||e.key===`Backspace`){if(e.preventDefault(),F===`measure`){or!==null&&(ir(e=>e.filter(e=>e.id!==or)),sr(null));return}Cr();return}if(e.key===`+`||e.key===`=`){kr(1.25);return}if(e.key===`-`){kr(1/1.25);return}if(e.key===`0`){hr();return}if(e.key.startsWith(`Arrow`)){e.preventDefault();let t={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[e.key];t&&Nr(t[0],t[1]);return}let r=e.key.toLowerCase();if(r===`s`){Zn(e=>!e);return}if(r===`l`){$n(e=>!e);return}if(r===`g`){tr(e=>!e);return}let i=ct[e.key.toLowerCase()];i&&q&&Ot.includes(i)&&(Ln(i),wr())},[w,q,Ot,F,U,K.length,or,jr,Ar,R,wr,Cr,kr,hr,Nr,Ln,Mt,Mr]),Q=m((e,t,n)=>{bn.current=e,n?.resetHistory?(j.clearHistory(),j.replace(e)):j.commit(e,t);let r={reason:t,committed:!0,targetIds:[]};S?.(e,r),yt?.(e,r)},[j,S,yt]),Fr=m((e={})=>{let{plan:t,floor:n}=ue(M,{...e,index:he(M,N.id)+1});return Q(t,`add-floor`),Pn(n.id),n.id},[M,N.id,Q,Pn]),Ir=m(()=>{let{plan:e,floor:t}=de(M,N.id);return t?(Q(e,`duplicate-floor`),Pn(t.id),t.id):null},[M,N.id,Q,Pn]),Lr=m(e=>{let t=e??N.id,n=ve(M,t);if(n!==M&&(Q(n,`remove-floor`),t===N.id)){let e=he(M,t);Pn(n.floors[Math.max(0,e-1)].id)}},[M,N.id,Q,Pn]),Rr=m((e,t)=>{let n=_e(M,e,t);n!==M&&Q(n,`move-floor`)},[M,Q]),zr=m((e,t)=>{let n=xe(M,e,t);n!==M&&Q(n,`edit-floor`)},[M,Q]),Br=m((e,t)=>{let n=ye(M,e,t);n!==M&&Q(n,`rename-floor`)},[M,Q]),Vr=m(e=>{let t=(e??nn??M.name??``).trim()||`floor-plan`,n=URL.createObjectURL(new Blob([je(M)],{type:`application/json`})),r=document.createElement(`a`);r.href=n,r.download=t.endsWith(`.json`)?t:`${t}.json`,r.click(),setTimeout(()=>URL.revokeObjectURL(n),0)},[nn,M]),Hr=m(e=>{let t=Ae(e);return t.plan&&Q(t.plan,`import`),dr(t.plan&&t.issues.length===0?null:t.issues),rn?.(t),t},[rn,Q]),Ur=m(e=>{e.text().then(e=>Hr(e)).catch(e=>{let t=[`Could not read that file: ${e.message}`];dr(t),rn?.({plan:null,issues:t})})},[Hr,rn]),Wr=m(()=>ir([]),[]),Gr=m(e=>{e.key===`Shift`&&(Tn.current=!1),e.key===`Alt`&&(wn.current=!1),e.key===` `&&(Cn.current=!1)},[]);Ie(Fe,()=>({getPlan:()=>M,setPlan:(e,t)=>Q(e,`import`,t),clear:()=>Q(fe(),`clear`),getFloorId:()=>N.id,setFloorId:Pn,addFloor:e=>Fr(e),duplicateFloor:Ir,removeFloor:Lr,renameFloor:Br,moveFloor:Rr,setFloorHeight:zr,clearMeasurements:Wr,download:Vr,loadJson:Hr,undo:Ar,redo:jr,canUndo:()=>an!==`none`&&j.canUndo,canRedo:()=>an!==`none`&&j.canRedo,clearHistory:j.clearHistory,getSelection:()=>[...L.current],select:R,addToSelection:e=>{let t=Array.isArray(e)?e:[e],n=new Set(L.current.map(e=>`${e.type}:${e.id}`));R([...L.current,...t.filter(e=>!n.has(`${e.type}:${e.id}`))])},toggleSelection:Bn,selectAll:Mr,deleteSelection:Cr,getView:()=>B,setView:V,zoomBy:kr,fitToContent:hr,toWorld:pr,toScreen:J,getSvgElement:()=>yn.current}),[M,j,Q,N,Pn,Fr,Ir,Lr,Br,Rr,zr,Wr,Vr,Hr,Ar,jr,an,R,Bn,Mr,Cr,B,V,kr,hr,pr,J]);let $=A.current,Kr=Le(()=>{if(!q)return null;let e=[],t=[...K,...$.kind===`measure`?[{id:-1,a:$.start,b:$.current}]:[]];for(let n of t){let t=J(n.a),r=J(n.b),i=Math.hypot(n.b.x-n.a.x,n.b.y-n.a.y);if(i<ft)continue;let a=Math.atan2(n.b.y-n.a.y,n.b.x-n.a.x),o=-Math.sin(a)*5,s=Math.cos(a)*5,c={x:(t.x+r.x)/2,y:(t.y+r.y)/2};if(e.push(b(`g`,{className:v(p.roomDrawerMeasureLine,or===n.id&&p.roomDrawerMeasureLineHovered,D?.measureLine),children:[y(`line`,{x1:t.x,y1:t.y,x2:r.x,y2:r.y}),y(`line`,{x1:t.x-o,y1:t.y-s,x2:t.x+o,y2:t.y+s}),y(`line`,{x1:r.x-o,y1:r.y-s,x2:r.x+o,y2:r.y+s})]},`measure-${n.id}`)),F===`measure`&&n.id>=0)for(let[i,a]of[[`a`,t],[`b`,r]])e.push(y(`circle`,{className:p.roomDrawerMeasureGrip,cx:a.x,cy:a.y,r:4},`measure-grip-${n.id}-${i}`));e.push(y(`text`,{className:v(p.roomDrawerMeasure,D?.measureLine),x:c.x,y:c.y-8,textAnchor:`middle`,children:`${Yt(i)} · ${_t(a)}`},`measure-label-${n.id}`))}if(Wt&&G&&(G.guides.forEach((t,n)=>{let r=J(t.a),i=J(t.b);e.push(y(`line`,{className:v(p.roomDrawerGuide,t.kind===f.Angle&&p.roomDrawerGuideAngle),x1:r.x,y1:r.y,x2:i.x,y2:i.y},`guide-${n}`))}),G.kind!==f.None&&G.kind!==f.Grid)){let t=J(G.point);e.push(y(`rect`,{className:p.roomDrawerSnapMarker,x:t.x-4,y:t.y-4,width:8,height:8},`snap-marker`))}if($.kind===`rect`){let t=J($.start),n=J($.current),r=Math.min(t.x,n.x),i=Math.min(t.y,n.y),a=Math.max(t.x,n.x),o=Math.max(t.y,n.y);e.push(y(`rect`,{className:p.roomDrawerPreview,x:r,y:i,width:a-r,height:o-i},`rect-preview`));let s=Math.abs($.current.x-$.start.x),c=Math.abs($.current.y-$.start.y);Jt&&(s>0||c>0)&&(e.push(y(`text`,{className:p.roomDrawerMeasure,x:(r+a)/2,y:i-8,textAnchor:`middle`,children:Yt(s)},`rect-width`),y(`text`,{className:p.roomDrawerMeasure,x:r-8,y:(i+o)/2,textAnchor:`end`,dominantBaseline:`central`,children:Yt(c)},`rect-height`)),s>0&&c>0&&e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureSecondary),x:(r+a)/2,y:(i+o)/2,textAnchor:`middle`,dominantBaseline:`central`,children:Xt(s*c)},`rect-area`)))}if(F===`wall`&&U.length>0){let t=[...U,W].filter(Boolean).map(J);if(e.push(y(`polyline`,{className:p.roomDrawerPreview,points:t.map(e=>`${e.x},${e.y}`).join(` `),fill:`none`},`chain`)),t.forEach((t,n)=>{e.push(y(`circle`,{className:p.roomDrawerHandle,cx:t.x,cy:t.y,r:4},`chain-dot-${n}`))}),Jt&&W&&U.length>0){let t=U[U.length-1],n=Math.hypot(W.x-t.x,W.y-t.y),r=J({x:(t.x+W.x)/2,y:(t.y+W.y)/2}),i=G?.kind===f.Angle;e.push(y(`text`,{className:v(p.roomDrawerMeasure,i&&p.roomDrawerMeasureLocked),x:r.x,y:r.y-8,textAnchor:`middle`,children:`${Yt(n)} · ${_t(G?.angleRelativeTo===`reference`&&fr!==void 0?Math.atan2(W.y-t.y,W.x-t.x)-fr:Math.atan2(W.y-t.y,W.x-t.x))}${G?.angleRelativeTo===`reference`?` rel`:``}`},`chain-len`))}}let n=new Set(I.filter(e=>e.type===`node`).map(e=>e.id));for(let t of Hn){let r=N.nodes[t];if(!r)continue;let i=J(r);e.push(y(`circle`,{className:v(p.roomDrawerHandle,n.has(t)&&p.roomDrawerHandleActive),cx:i.x,cy:i.y,r:5},`handle-${t}`))}if($.kind===`marquee`&&Sn.current?.moved){let t=J($.start),n=J($.current);e.push(y(`rect`,{className:p.roomDrawerMarquee,x:Math.min(t.x,n.x),y:Math.min(t.y,n.y),width:Math.abs(n.x-t.x),height:Math.abs(n.y-t.y)},`marquee`))}if(br&&$.kind!==`node`){let t=J(br);e.push(y(`circle`,{className:p.roomDrawerMidHandle,cx:t.x,cy:t.y,r:4},`midpoint`))}if(Jt&&$.kind===`room`&&$.moved){let t=new Set($.nodeIds),n=$.nodeIds.find(e=>N.nodes[e]&&$.orig[e]);if(n){let t=N.nodes[n],r=$.orig[n],i=t.x-r.x,a=t.y-r.y,o=z?.type===`room`?P.find(e=>e.roomId===z.id):void 0,s=J(o?o.anchor:t);e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureOffset),x:s.x,y:s.y-26,textAnchor:`middle`,children:`${Yt(Math.hypot(i,a))} · ${_t(Math.atan2(a,i))}`},`room-offset`))}for(let n of Object.values(N.walls)){if(t.has(n.a)===t.has(n.b))continue;let r=N.nodes[n.a],i=N.nodes[n.b];if(!r||!i)continue;let a=t.has(n.a)?r:i,o=t.has(n.a)?i:r,s=J({x:(r.x+i.x)/2,y:(r.y+i.y)/2});e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureSecondary),x:s.x,y:s.y-8,textAnchor:`middle`,children:`${Yt(Math.hypot(o.x-a.x,o.y-a.y))} · ${_t(Math.atan2(o.y-a.y,o.x-a.x))}`},`room-stretch-${n.id}`))}}if(Jt&&(z?.type===`node`||z?.type===`wall`)){let t=[],n=new Set,r=(e,r,i)=>{if(n.has(e))return;let a=N.walls[e];a&&(n.add(e),t.push({wall:a,from:r,primary:i}))};if(z.type===`node`)for(let e of Object.values(N.walls))(e.a===z.id||e.b===z.id)&&r(e.id,z.id,!0);else{let e=N.walls[z.id];if(e){r(e.id,e.a,!0);for(let t of Object.values(N.walls))if(t.id!==e.id)for(let n of[e.a,e.b])(t.a===n||t.b===n)&&r(t.id,n,!1)}}let i=G?.kind===f.Angle&&$.kind!==`none`;for(let{wall:n,from:r,primary:a}of t){let t=N.nodes[n.a],o=N.nodes[n.b];if(!t||!o)continue;let s=n.a===r?t:o,c=n.a===r?o:t,l=J({x:(t.x+o.x)/2,y:(t.y+o.y)/2});e.push(y(`text`,{className:v(p.roomDrawerMeasure,!a&&p.roomDrawerMeasureSecondary,a&&i&&p.roomDrawerMeasureLocked),x:l.x,y:l.y-8,textAnchor:`middle`,children:`${Yt(Math.hypot(c.x-s.x,c.y-s.y))} · ${_t(Math.atan2(c.y-s.y,c.x-s.x))}`},`measure-${n.id}`))}}return y(ot,{children:e})},[q,$,F,U,W,I,N,P,z,Hn,br,Jt,Wt,G,fr,Yt,Xt,K,or,D?.measureLine,J]),qr={select:{icon:Be,label:T?.select??`Select and edit`,key:`V`},wall:{icon:$e,label:T?.wall??`Draw walls`,key:`W`},rect:{icon:nt,label:T?.rect??`Draw a room`,key:`R`},door:{icon:Ge,label:T?.door??`Add a door`,key:`D`},window:{icon:at,label:T?.window??`Add a window`,key:`N`},archway:{icon:Je,label:T?.archway??`Add an archway`,key:`A`},measure:{icon:tt,label:T?.measure??`Measure`,key:`M`}},Jr=q?F===`wall`?T?.hintWall??`Click to place corners · Shift for a fixed angle, L to latch it · Click the first corner or press Enter to close`:F===`rect`?T?.hintRect??`Drag to draw a room`:F===`measure`?T?.hintMeasure??`Drag to measure · Drag an end or the line to adjust it · Delete removes one, Escape clears them`:lt[F]?T?.hintOpening??`Click a wall to cut an opening into it`:T?.hintSelect??(Mt?`Drag a corner to reshape · Drag a wall to push it, and the room next door moves with it · Ctrl-click or drag a box to select several · Delete to remove`:`Drag a corner to reshape · Drag a wall to push it, and the room next door moves with it · Drag the dot on a selected wall to add a corner · Delete to remove`):``,Yr=I.length===0?T?.selectedFloor??`Floor`:I.length>1?(T?.selectedCount??`{count} selected`).replace(`{count}`,String(I.length)):yr?T?.selectedOpening??ut[yr.kind]:Z?T?.selectedWall??`Wall`:z?.type===`room`?T?.selectedRoom??`Room`:T?.selectedCorner??`Corner`,Xr=q?Ot:[];return b(`div`,{...hn,ref:_n,className:v(p.roomDrawer,w&&p.roomDrawerDisabled,pn,D?.root),style:{...mn,...O?.root},role:`application`,"aria-label":fn??`Floor plan editor`,tabIndex:w?-1:0,onKeyDown:Pr,onKeyUp:Gr,children:[Zt&&b(`div`,{className:v(p.roomDrawerToolbar,D?.toolbar),style:O?.toolbar,role:`toolbar`,"aria-label":`Drawing tools`,children:[Xr.map(e=>{let n=qr[e];return y(`button`,{type:`button`,className:v(p.roomDrawerToolButton,e===F&&p.roomDrawerToolButtonActive,D?.toolButton),style:O?.toolButton,title:`${n.label} (${n.key})`,"aria-label":n.label,"aria-pressed":e===F,onClick:()=>{Ln(e),wr()},children:t(E?.[e]??n.icon,{className:v(p.roomDrawerToolIcon,D?.toolIcon),style:O?.toolIcon})},e)}),Xr.length>0&&y(`span`,{className:p.roomDrawerToolbarSeparator}),q&&b(ot,{children:[[{on:Xn,toggle:()=>Zn(e=>!e),icon:E?.snap??Xe,label:T?.snap??`Snap to grid and geometry`,key:`S`},{on:Qn,toggle:()=>$n(e=>!e),icon:E?.angleLock??qe,label:T?.angleLock??`Lock to ${Ut}° angles`,key:`L`},{on:er,toggle:()=>tr(e=>!e),icon:E?.grid??Ue,label:T?.grid??`Show grid`,key:`G`},...pe(M,N.id)?[{on:jn,toggle:()=>Mn(e=>!e),icon:E?.underlay??Ye,label:T?.underlay??`Show the floor below`,key:`B`}]:[]].map(e=>y(`button`,{type:`button`,className:v(p.roomDrawerToolButton,e.on&&p.roomDrawerToolButtonOn,D?.toolButton),style:O?.toolButton,title:`${e.label} (${e.key})`,"aria-label":e.label,"aria-pressed":e.on,onClick:e.toggle,children:t(e.icon,{className:v(p.roomDrawerToolIcon,D?.toolIcon),style:O?.toolIcon})},e.key)),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),en&&an!==`none`&&q&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.undo??`Undo`,"aria-label":T?.undo??`Undo`,disabled:!j.canUndo,onClick:Ar,children:t(E?.undo??Ve)}),y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.redo??`Redo`,"aria-label":T?.redo??`Redo`,disabled:!j.canRedo,onClick:jr,children:t(E?.redo??He)}),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),tn&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.download??`Download plan`,"aria-label":T?.download??`Download plan`,onClick:()=>Vr(),children:t(E?.download??Ke)}),q&&y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.upload??`Open a plan file`,"aria-label":T?.upload??`Open a plan file`,onClick:()=>cr.current?.click(),children:t(E?.upload??it)}),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),b(`div`,{className:v(p.roomDrawerViewControls,D?.viewControls),style:O?.viewControls,children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.zoomOut??`Zoom out`,"aria-label":T?.zoomOut??`Zoom out`,onClick:()=>kr(1/1.25),children:t(E?.zoomOut??Ze)}),b(`button`,{type:`button`,className:v(p.roomDrawerZoomLabel,D?.zoomLabel),style:O?.zoomLabel,title:T?.fit??`Fit to content`,onClick:()=>hr(),children:[Math.round(B.zoom*1e3)/10,`%`]}),y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.zoomIn??`Zoom in`,"aria-label":T?.zoomIn??`Zoom in`,onClick:()=>kr(1.25),children:t(E?.zoomIn??Qe)})]})]}),Ct&&M.floors.length>0&&b(`div`,{className:v(p.roomDrawerFloorBar,D?.floorBar),style:O?.floorBar,role:`tablist`,"aria-label":T?.selectedFloor??`Floor`,children:[[...M.floors].reverse().map(e=>y(`button`,{type:`button`,role:`tab`,className:v(p.roomDrawerFloorTab,e.id===N.id&&p.roomDrawerFloorTabActive,D?.floorTab),style:O?.floorTab,"aria-selected":e.id===N.id,onClick:()=>Pn(e.id),children:e.label},e.id)),q&&y(`button`,{type:`button`,className:v(p.roomDrawerFloorTab,p.roomDrawerFloorTabAdd),title:T?.addFloor??`Add a floor above`,"aria-label":T?.addFloor??`Add a floor above`,onClick:()=>Fr(),children:t(E?.addFloor??et)})]}),y(`div`,{ref:vn,className:v(p.roomDrawerCanvasWrapper,q&&F!==`select`&&p.roomDrawerCanvasWrapperDrawing,D?.canvasWrapper),style:{height:ln,...O?.canvasWrapper},onPointerDown:Tr,onPointerMove:Er,onPointerUp:e=>Dr(e,!1),onPointerCancel:e=>Dr(e,!0),children:y(Ne,{ref:yn,floor:N,underlay:Nn,rooms:P,view:B,size:H,selection:I,hovered:Un,interactiveRooms:!1,showGrid:er,gridSize:C,showRoomLabels:!0,formatArea:Xt,getRoomColor:un,renderRoomLabel:dn,overlay:Kr,classNames:D,styles:O})}),Qt&&q&&b(`div`,{className:v(p.roomDrawerInspector,D?.inspector),style:O?.inspector,children:[y(`span`,{className:v(p.roomDrawerInspectorKind,I.length===0&&p.roomDrawerInspectorKindEmpty,D?.inspectorLabel),children:Yr}),I.length===0&&b(ot,{children:[y(i,{className:v(p.roomDrawerInspectorName,D?.inspectorField),style:O?.inspectorField,label:T?.floorName??`Floor name`,value:N.label,onChange:e=>Br(N.id,e)}),y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.floorHeight??`Height (mm)`,title:`Storey height. The floors above move to sit on top of it.`,value:N.height,decimalScale:0,min:500,step:100,showArrows:!0,onChange:e=>{e!==void 0&&zr(N.id,e)}}),M.floors.length>1&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.moveFloorUp??`Move this floor up`,"aria-label":T?.moveFloorUp??`Move this floor up`,disabled:he(M,N.id)>=M.floors.length-1,onClick:()=>Rr(N.id,he(M,N.id)+1),children:t(E?.moveFloorUp??ze)}),y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.moveFloorDown??`Move this floor down`,"aria-label":T?.moveFloorDown??`Move this floor down`,disabled:he(M,N.id)<=0,onClick:()=>Rr(N.id,he(M,N.id)-1),children:t(E?.moveFloorDown??Re)})]}),y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.duplicateFloor??`Copy this floor to a new one above`,onClick:()=>Ir(),children:t(E?.duplicateFloor??We)}),M.floors.length>1&&y(n,{className:p.roomDrawerInspectorDelete,icon:E?.delete??rt,title:T?.deleteFloor??`Delete this floor`,onClick:()=>Lr()})]}),vr?.meta&&b(ot,{children:[y(i,{className:v(p.roomDrawerInspectorName,D?.inspectorField),style:O?.inspectorField,label:T?.roomName??`Room name`,value:vr.meta.name,onChange:e=>{let t=vr.meta;X({...N,rooms:{...N.rooms,[t.id]:{...t,name:e}}},`edit-room`,[t.id])}}),y(`span`,{className:v(p.roomDrawerInspectorLabel,D?.inspectorLabel),children:Xt(vr.area)})]}),Z&&y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,onClick:xr,title:T?.addCorner??`Add a corner to this wall`,children:T?.addCorner??`Add corner`}),Z&&y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.thickness??`Thickness (mm)`,value:Z.thickness,decimalScale:0,min:10,showArrows:!0,step:10,onChange:e=>{e!==void 0&&X({...N,walls:{...N.walls,[Z.id]:{...Z,thickness:e}}},`edit-wall`,[Z.id])}}),yr&&b(ot,{children:[y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.width??`Width (mm)`,value:yr.width,decimalScale:0,min:100,step:50,showArrows:!0,onChange:e=>{e!==void 0&&X(ce(N,yr.id,{width:e}).floor,`edit-opening`,[yr.id])}}),y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.sill??`Sill (mm)`,title:`How far above the floor the opening starts. Stored for a 3D view; it does not change the plan.`,showArrows:!0,value:yr.sill,decimalScale:0,min:0,step:50,onChange:e=>{e!==void 0&&X(ce(N,yr.id,{sill:e}).floor,`edit-opening`,[yr.id])}})]}),I.length>0&&y(n,{className:p.roomDrawerInspectorDelete,icon:E?.delete??rt,title:T?.deleteSelection??`Delete selection`,onClick:Cr})]}),tn&&q&&y(`input`,{ref:cr,type:`file`,accept:`application/json,.json`,className:p.roomDrawerFileInput,tabIndex:-1,"aria-hidden":`true`,onChange:e=>{let t=e.target.files?.[0];e.target.value=``,t&&Ur(t)}}),$t&&(ur!==null||Jr)&&y(`div`,{className:v(p.roomDrawerHint,ur!==null&&p.roomDrawerHintReport,D?.hint),style:O?.hint,role:ur===null?void 0:`status`,children:ur===null?Jr:ur.length===0?T?.importFailed??`That file could not be read as a floor plan`:ur.join(` · `)})]})});export{x as default};
1
+ import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"../actionIcon/actionIcon.mjs";import r from"../hooks/useCoarsePointer.mjs";import i from"../input/input.mjs";import{OpeningKind as a,WallType as o}from"../floorPlan/floorPlan.types.mjs";import{pointToSegment as s}from"../floorPlan/floorPlan.geometry.mjs";import{DEFAULT_WALL_ATTRS as c,addOpening as l,addRect as ee,addWall as u,detachWall as te,dissolveNode as ne,mergeNodes as re,moveNode as ie,removeOpening as ae,removeWall as oe,splitWall as se,updateOpening as ce,weldShortWalls as le}from"../floorPlan/floorPlan.graph.mjs";import{addFloor as ue,duplicateFloor as de,emptyFloorPlan as fe,floorBelow as pe,floorBounds as me,floorIndex as he,getFloor as ge,moveFloor as _e,removeFloor as ve,renameFloor as ye,setFloor as be,setFloorHeight as xe}from"../floorPlan/floorPlan.plan.mjs";import{commitDerivation as Se,derivePlan as Ce}from"../floorPlan/floorPlan.rooms.mjs";import{HIT_PX as we,HIT_PX_COARSE as Te,hitTest as Ee,selectionsEqual as De,worldTolerances as d}from"../floorPlan/floorPlan.hit.mjs";import{SnapKind as f,clientToWorld as Oe,resolveSnap as ke}from"../floorPlan/floorPlan.snap.mjs";import{planFromJson as Ae,planToJson as je}from"../floorPlan/floorPlan.json.mjs";import Me from"../numberInput/index.mjs";import Ne from"../planCanvas/planCanvas.mjs";import{usePlanHistory as Pe}from"./usePlanHistory.mjs";import p from"./roomDrawer.module.mjs";import{forwardRef as Fe,useCallback as m,useEffect as h,useImperativeHandle as Ie,useMemo as Le,useRef as g,useState as _}from"react";import v from"classnames";import{faAngleDown as Re,faAngleUp as ze,faArrowPointer as Be,faArrowRotateLeft as Ve,faArrowRotateRight as He,faBorderAll as Ue,faClone as We,faDoorOpen as Ge,faDownload as Ke,faDraftingCompass as qe,faExpand as Je,faLayerGroup as Ye,faMagnet as Xe,faMagnifyingGlassMinus as Ze,faMagnifyingGlassPlus as Qe,faMinus as $e,faPlus as et,faRulerCombined as tt,faSquare as nt,faTrash as rt,faUpload as it,faWindowMaximize as at}from"@fortawesome/free-solid-svg-icons";import{Fragment as ot,jsx as y,jsxs as b}from"react/jsx-runtime";var st=[`select`,`wall`,`rect`,`door`,`window`,`archway`,`measure`],ct={v:`select`,w:`wall`,r:`rect`,d:`door`,n:`window`,a:`archway`,m:`measure`},lt={door:a.Door,window:a.Window,archway:a.Archway},ut={[a.Door]:`Door`,[a.Window]:`Window`,[a.Archway]:`Archway`,[a.Gap]:`Gap`},dt={[a.Door]:{width:900,sill:0,head:2100},[a.Window]:{width:1200,sill:900,head:2100},[a.Archway]:{width:1200,sill:0,head:2100},[a.Gap]:{width:1e3,sill:0,head:2500}},ft=1,pt=4,mt=[];function ht(e){return e>=1e3?`${(e/1e3).toFixed(2)} m`:`${Math.round(e)} mm`}function gt(e){let t=e/1e6;return`${t.toFixed(+(t<10))} m²`}function _t(e){let t=e*180/Math.PI;return t=(t%360+360)%360,t>180&&(t-=360),`${Math.abs(t)<.05?0:Math.round(t*10)/10}°`}var x=Fe(function(a,Fe){let{value:x,defaultValue:vt,onChange:S,onChangeEnd:yt,floorId:bt,defaultFloorId:xt,onFloorChange:St,showFloorBar:Ct=!0,showUnderlay:wt=!0,tool:Tt,defaultTool:Et=`select`,onToolChange:Dt,tools:Ot=st,selection:kt,defaultSelection:At,onSelectionChange:jt,multiSelect:Mt=!0,onHoverChange:Nt,view:Pt,defaultView:Ft,onViewChange:It,minZoom:Lt=.005,maxZoom:Rt=2,fitOnMount:zt=!0,gridSize:C=100,showGrid:Bt=!0,snap:Vt=!0,angleLock:Ht=!1,constrainAngle:Ut=45,showSnapGuides:Wt=!0,wallThickness:Gt=c.thickness,wallHeight:Kt,openingDefaults:qt,showMeasurements:Jt=!0,formatLength:Yt=ht,formatArea:Xt=gt,showToolbar:Zt=!0,showInspector:Qt=!0,showHint:$t=!0,showHistoryControls:en=!0,showFileControls:tn=!0,fileName:nn,onImport:rn,historyMode:an=`internal`,historyLimit:on=50,onHistoryChange:sn,readOnly:cn=!1,disabled:w=!1,canvasHeight:ln=`420px`,getRoomColor:un,renderRoomLabel:dn,labels:T,icons:E,"aria-label":fn,className:pn,style:mn,classNames:D,styles:O,...hn}=e(`RoomDrawer`,a),gn=r(),k=gn?Te:we,_n=g(null),vn=g(null),yn=g(null),bn=g(null),A=g({kind:`none`}),xn=g(new Map),Sn=g(null),Cn=g(!1),wn=g(!1),Tn=g(!1),En=Le(()=>vt??x??fe(),[]),j=Pe(En,on),Dn=x!==void 0,M=Dn?x:j.present;h(()=>{if(Dn&&x){if(x===bn.current){j.replace(x);return}j.commit(x,`external`)}},[x,Dn]);let[On,kn]=_(xt),An=bt??On??M.floors[0]?.id,N=Le(()=>ge(M,An)??ge(M)??fe().floors[0],[M,An]),[jn,Mn]=_(wt);h(()=>Mn(wt),[wt]);let Nn=Le(()=>jn?pe(M,N.id):null,[jn,M,N.id]),Pn=m(e=>{e!==N.id&&(bt===void 0&&kn(e),St?.(e))},[N.id,bt,St]),P=Le(()=>Ce(N),[N]).rooms,[Fn,In]=_(Et),F=Tt??Fn,Ln=m(e=>{Tt===void 0&&In(e),Dt?.(e)},[Tt,Dt]),[Rn,zn]=_(At??mt),I=kt===void 0?Rn:kt,L=g(I);L.current=I;let R=m(e=>{let t=e===null?mt:Array.isArray(e)?e:[e];L.current=t,kt===void 0&&zn(t),jt?.([...t])},[kt,jt]),Bn=m(e=>{let t=L.current,n=t.filter(t=>t.type!==e.type||t.id!==e.id);R(n.length===t.length?[...t,e]:n)},[R]),z=I.length===1?I[0]:null,Vn=m(e=>{let t=new Set;for(let n of e)if(n.type===`node`)t.add(n.id);else if(n.type===`wall`){let e=N.walls[n.id];e&&(t.add(e.a),t.add(e.b))}else if(n.type===`room`){let e=P.find(e=>e.roomId===n.id);for(let n of e?.nodeIds??[])t.add(n)}return t},[N.walls,P]),Hn=Le(()=>Vn(I),[Vn,I]),[Un,Wn]=_(null),[Gn,Kn]=_(Ft??{x:0,y:0,zoom:.05}),B=Pt??Gn,V=m(e=>{Pt===void 0&&Kn(e),It?.(e)},[Pt,It]),[H,qn]=_({width:800,height:420}),[U,Jn]=_([]),[W,Yn]=_(null),[Xn,Zn]=_(Vt),[Qn,$n]=_(Ht);h(()=>Zn(Vt),[Vt]),h(()=>$n(Ht),[Ht]);let[er,tr]=_(Bt);h(()=>tr(Bt),[Bt]);let nr=g(null),[G,rr]=_(null),[K,ir]=_([]),ar=g(0),[or,sr]=_(null),cr=g(null),lr=m(e=>{let t=d(k,B.zoom);for(let n=K.length-1;n>=0;n--){let r=K[n];if(Math.hypot(e.x-r.a.x,e.y-r.a.y)<=t.node)return{id:r.id,end:`a`};if(Math.hypot(e.x-r.b.x,e.y-r.b.y)<=t.node)return{id:r.id,end:`b`}}for(let n=K.length-1;n>=0;n--){let r=K[n];if(s(e,r.a,r.b).dist<=t.wall)return{id:r.id}}return null},[K,k,B.zoom]),[ur,dr]=_(null),q=!cn&&!w,fr=Le(()=>{if(U.length<2)return;let e=U[U.length-2],t=U[U.length-1];return Math.atan2(t.y-e.y,t.x-e.x)},[U]);h(()=>{let e=vn.current;if(!e)return;let t=new ResizeObserver(()=>{let t=e.getBoundingClientRect();t.width>0&&t.height>0&&qn({width:Math.round(t.width),height:Math.round(t.height)})});t.observe(e);let n=e.getBoundingClientRect();return n.width>0&&n.height>0&&qn({width:Math.round(n.width),height:Math.round(n.height)}),()=>t.disconnect()},[]);let pr=m((e,t)=>{let n=vn.current?.getBoundingClientRect()??{left:0,top:0};return Oe(e,t,n,B)},[B]),J=m(e=>({x:(e.x-B.x)*B.zoom,y:(e.y-B.y)*B.zoom}),[B]),Y=m((e,t,n,r,i)=>{let a=Xn!==wn.current,o=Qn!==Tn.current,s=ke(e,{floor:N,pxToWorld:B.zoom>0?1/B.zoom:1,origin:t,referenceAngle:r,excludeNodeIds:n,excludeWallIds:i,options:{enabled:a?[f.Node,f.Intersection,f.Wall,f.Angle,f.Extension,f.Alignment,f.Grid]:[],gridSize:C,angleStepDeg:o?Ut:0,toleranceScreenPx:gn?16:10}});return nr.current=s,s},[N,B.zoom,Xn,Qn,C,Ut,gn]),mr=m(e=>{let t=Object.values(N.walls).filter(t=>t.a===e||t.b===e),n=new Set(t.map(e=>e.id)),r=N.nodes[e];if(!r)return{excludeWallIds:n};let i={x:r.x,y:r.y},a,o=t[0];if(o){let t=o.a===e?o.b:o.a,n=N.nodes[t];n&&(a=Math.atan2(n.y-r.y,n.x-r.x))}return{origin:i,referenceAngle:a,excludeWallIds:n}},[N]),hr=m((e={})=>{let t=e.padding??24,n=me(N);if(!n||n.width<=0||n.height<=0){V({x:-1e3,y:-1e3,zoom:.05});return}let r=Math.min((H.width-t*2)/n.width,(H.height-t*2)/n.height),i=Math.max(Lt,Math.min(Rt,r));V({x:n.minX-(H.width/i-n.width)/2,y:n.minY-(H.height/i-n.height)/2,zoom:i})},[N,H.width,H.height,Lt,Rt,V]),gr=g(!1);h(()=>{zt&&!gr.current&&Object.keys(N.nodes).length!==0&&(H.width<=1||(gr.current=!0,hr()))},[zt,N,H.width,hr]);let _r=m((e,t,n,r=[],i={})=>{if(e===N)return M;let a=be(M,e);bn.current=a,n?i.push===!1?j.replace(a):j.commit(a,t,r):j.updateGesture(a);let o={reason:t,committed:n,targetIds:r};return S?.(a,o),n&&yt?.(a,o),a},[N,M,j,S,yt]),X=m((e,t,n=[],r={})=>{let i=Se(le(e).floor).floor;return _r(i,t,!0,n,r)},[_r]);h(()=>{sn?.({canUndo:j.canUndo,canRedo:j.canRedo})},[j.canUndo,j.canRedo,sn]);let vr=Le(()=>z?.type===`room`?P.find(e=>e.roomId===z.id)??null:null,[z,P]),Z=z?.type===`wall`?N.walls[z.id]:void 0,yr=z?.type===`opening`?N.openings[z.id]:void 0,br=Le(()=>{if(!Z)return null;let e=N.nodes[Z.a],t=N.nodes[Z.b];return!e||!t?null:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}},[Z,N.nodes]),xr=m(()=>{if(!q||!Z)return;let e=se(N,Z.id,.5);e.result.wallIds&&(X(e.floor,`edit-wall`,[e.result.nodeId]),R({type:`node`,id:e.result.nodeId}))},[q,Z,N,X,R]),Sr=m((e,t,n=new Set)=>{if(e.type===`wall`)return{floor:oe(t,e.id).floor};if(e.type===`opening`)return{floor:ae(t,e.id).floor};if(e.type===`node`){let n=ne(t,e.id,{force:!0});if(n.result)return{floor:n.floor,reselect:{type:`wall`,id:n.result.wallId}};let r=t;for(let n of Object.values(t.walls))(n.a===e.id||n.b===e.id)&&(r=oe(r,n.id,{dissolveCollinear:!1}).floor);return{floor:r}}let r=P.find(t=>t.roomId===e.id);if(!r)return{floor:t};let i=new Set;for(let t of P)if(t.roomId!==e.id&&!(t.roomId&&n.has(t.roomId)))for(let e of t.wallIds)i.add(e);let a=t;for(let e of new Set(r.wallIds))i.has(e)||(a=oe(a,e,{dissolveCollinear:!1}).floor);let o={...a.rooms};return delete o[e.id],{floor:{...a,rooms:o}}},[P]),Cr=m(()=>{let e=L.current;if(!q||e.length===0)return;let t={room:0,opening:1,wall:2,node:3},n=[...e].sort((e,n)=>t[e.type]-t[n.type]),r=new Set(n.filter(e=>e.type===`room`).map(e=>e.id)),i=N,a;for(let e of n){let t=Sr(e,i,r);i=t.floor,n.length===1&&(a=t.reselect)}i!==N&&(X(i,`delete`,n.map(e=>e.id)),R(a??null))},[q,N,Sr,X,R]),wr=m(()=>{Jn(e=>e.length===0?e:[]),rr(null)},[]);h(()=>{wr()},[F,wr]);let Tr=m(e=>{if(w)return;if(_n.current?.focus(),dr(null),xn.current.set(e.pointerId,{x:e.clientX,y:e.clientY}),e.currentTarget.setPointerCapture?.(e.pointerId),xn.current.size===2){let[e,t]=[...xn.current.values()];A.current.kind!==`none`&&A.current.kind!==`pan`&&j.cancelGesture(),A.current={kind:`pinch`,startDist:Math.hypot(t.x-e.x,t.y-e.y),startView:B,startMid:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}};return}if(xn.current.size>2)return;if(Sn.current={client:{x:e.clientX,y:e.clientY},moved:!1},e.button===1||Cn.current){A.current={kind:`pan`,startClient:{x:e.clientX,y:e.clientY},startView:B};return}if(e.button!==0)return;let t=pr(e.clientX,e.clientY);if(!q){let e=Ee(N,P,t,d(k,B.zoom));R(e);return}if(F===`rect`){let e=Y(t).point;A.current={kind:`rect`,start:e,current:e},j.beginGesture();return}if(F===`measure`){let e=lr(t);if(e){let n=K.find(t=>t.id===e.id);A.current=e.end?{kind:`measureEnd`,id:e.id,end:e.end}:{kind:`measureMove`,id:e.id,startWorld:t,origA:n.a,origB:n.b};return}let n=Y(t).point;A.current={kind:`measure`,start:n,current:n};return}if(F===`wall`){let e=U[U.length-1],n=Y(t,e,void 0,fr).point;if(U.length===0){Jn([n]);return}let r=U[U.length-1],i=u(N,r,n,{thickness:Gt,type:o.Interior,height:Kt},d(k,B.zoom).node);i.result.wallIds.length>0&&X(i.floor,`draw-wall`,i.result.wallIds),U.length>=2&&Math.hypot(n.x-U[0].x,n.y-U[0].y)<d(k,B.zoom).node?wr():Jn(e=>[...e,n]);return}let n=lt[F];if(n){let e=d(k,B.zoom),r=Ee(N,P,t,e,{accept:[`wall`]});if(r?.type!==`wall`)return;let i=N.walls[r.id],a=N.nodes[i.a],o=N.nodes[i.b],s=Math.hypot(o.x-a.x,o.y-a.y),c=((t.x-a.x)*(o.x-a.x)+(t.y-a.y)*(o.y-a.y))/(s*s||1),ee={...dt[n],...qt?.[n]},u=l(N,{wallId:i.id,kind:n,offset:Math.min(Math.max(c,0),1)*s,width:ee.width,sill:ee.sill,head:ee.head});u.result.openingId&&(X(u.floor,`add-opening`,[u.result.openingId]),R({type:`opening`,id:u.result.openingId}));return}let r=d(k,B.zoom);if(br&&z?.type===`wall`&&Math.hypot(t.x-br.x,t.y-br.y)<=r.node){j.beginGesture(),A.current={kind:`wallSplit`,wallId:z.id,at:br};return}let i=Ee(N,P,t,r),a=Mt&&(e.ctrlKey||e.metaKey);if(!i){a||R(null),A.current=Mt?{kind:`marquee`,start:t,current:t,additive:a,base:L.current}:{kind:`none`};return}if((e.ctrlKey||e.metaKey)&&i.type===`wall`&&N.walls[i.id]){let e=N.walls[i.id];a||R(i),j.beginGesture(),A.current={kind:`wall`,wallId:i.id,startWorld:t,origA:{...N.nodes[e.a]},origB:{...N.nodes[e.b]},moved:!1,detach:!0,toggle:a};return}if(a){Bn(i),A.current={kind:`none`};return}if(L.current.some(e=>e.type===i.type&&e.id===i.id)||R(i),j.beginGesture(),L.current.length>1){let e=[...Vn(L.current)],n={};for(let t of e){let e=N.nodes[t];e&&(n[t]={x:e.x,y:e.y})}A.current={kind:`room`,nodeIds:e,startWorld:t,orig:n,moved:!1};return}if(i.type===`node`)A.current={kind:`node`,nodeId:i.id,moved:!1,...mr(i.id)};else if(i.type===`wall`){let e=N.walls[i.id];A.current={kind:`wall`,wallId:i.id,startWorld:t,origA:{...N.nodes[e.a]},origB:{...N.nodes[e.b]},moved:!1}}else if(i.type===`opening`)A.current={kind:`opening`,openingId:i.id,moved:!1};else{let e=P.find(e=>e.roomId===i.id),n=e?[...new Set(e.nodeIds)]:[],r={};for(let e of n){let t=N.nodes[e];t&&(r[e]={x:t.x,y:t.y})}A.current={kind:`room`,nodeIds:n,startWorld:t,orig:r,moved:!1}}},[w,q,B,F,N,P,k,pr,Y,U,Gt,Kt,qt,X,R,br,z,fr,mr,Vn,Mt,Bn,j,wr,lr,K]),Er=m(e=>{if(w)return;xn.current.has(e.pointerId)&&xn.current.set(e.pointerId,{x:e.clientX,y:e.clientY});let t=A.current;if(t.kind===`pinch`&&xn.current.size>=2){let[e,n]=[...xn.current.values()],r=Math.hypot(n.x-e.x,n.y-e.y);if(t.startDist<=0)return;let i=Math.max(Lt,Math.min(Rt,t.startView.zoom*(r/t.startDist))),a=vn.current?.getBoundingClientRect()??{left:0,top:0},o={x:(e.x+n.x)/2,y:(e.y+n.y)/2},s=Oe(t.startMid.x,t.startMid.y,a,t.startView);V({x:s.x-(o.x-a.left)/i,y:s.y-(o.y-a.top)/i,zoom:i});return}if(Sn.current){let t=e.clientX-Sn.current.client.x,n=e.clientY-Sn.current.client.y;Math.hypot(t,n)>pt&&(Sn.current.moved=!0)}if(t.kind===`pan`){V({x:t.startView.x-(e.clientX-t.startClient.x)/t.startView.zoom,y:t.startView.y-(e.clientY-t.startClient.y)/t.startView.zoom,zoom:t.startView.zoom});return}let n=pr(e.clientX,e.clientY);if(Yn(n),t.kind===`none`){if(!q)return;if(F===`wall`&&U.length>0){let e=Y(n,U[U.length-1],void 0,fr);Yn(e.point),rr(e);return}if(F===`select`){let e=Ee(N,P,n,d(k,B.zoom));De(e,Un)||(Wn(e),Nt?.(e))}F===`measure`&&sr(lr(n)?.id??null);return}if(Sn.current?.moved){if(t.kind===`measureEnd`){let e=Y(n).point;ir(n=>n.map(n=>n.id===t.id?{...n,[t.end]:e}:n)),Yn(e);return}if(t.kind===`measureMove`){let e=n.x-t.startWorld.x,r=n.y-t.startWorld.y;ir(n=>n.map(n=>n.id===t.id?{...n,a:{x:t.origA.x+e,y:t.origA.y+r},b:{x:t.origB.x+e,y:t.origB.y+r}}:n));return}if(t.kind===`rect`||t.kind===`measure`){A.current={...t,current:Y(n).point},Yn(Y(n).point);return}if(t.kind===`marquee`){A.current={...t,current:n},Yn(n);return}if(t.kind===`wallSplit`){let e=se(N,t.wallId,t.at);if(!e.result.wallIds){A.current={kind:`none`};return}let r=e.result.nodeId,i=N.walls[t.wallId],a=i?e.floor.nodes[i.a]:void 0,o=i?e.floor.nodes[i.b]:void 0,s={origin:a?{x:a.x,y:a.y}:void 0,referenceAngle:a&&o?Math.atan2(o.y-a.y,o.x-a.x):void 0,excludeWallIds:new Set(e.result.wallIds)},c=Y(n,s.origin,new Set([r]),s.referenceAngle,s.excludeWallIds).point;A.current={kind:`node`,nodeId:r,moved:!0,...s},R({type:`node`,id:r}),rr(nr.current),_r(ie(e.floor,r,c).floor,`move-node`,!1,[r]);return}if(t.kind===`node`){let e=Y(n,t.origin,new Set([t.nodeId]),t.referenceAngle,t.excludeWallIds).point;rr(nr.current),A.current={...t,moved:!0},_r(ie(N,t.nodeId,e).floor,`move-node`,!1,[t.nodeId]);return}if(t.kind===`wall`){let e=N.walls[t.wallId];if(!e)return;let r=t.origB.x-t.origA.x,i=t.origB.y-t.origA.y,a=Math.hypot(r,i);if(a<1e-6)return;let o={x:-i/a,y:r/a},s=(n.x-t.startWorld.x)*o.x+(n.y-t.startWorld.y)*o.y,c=Vt!==wn.current&&C>0?C:1,l=Math.round(s/c)*c,ee=Math.max(c,10);if(t.detach){if(Math.abs(l)<ee)return;let e=te(N,t.wallId,{x:o.x*l,y:o.y*l});if(!e.result)return;A.current={...t,detach:!1,toggle:!1,detachedSign:Math.sign(l),moved:!0},R({type:`wall`,id:t.wallId}),_r(e.floor,`move-wall`,!1,[t.wallId]);return}let u=ie(N,e.a,{x:t.origA.x+o.x*l,y:t.origA.y+o.y*l}).floor;u=ie(u,e.b,{x:t.origB.x+o.x*l,y:t.origB.y+o.y*l}).floor,t.detachedSign&&Math.abs(l)<10?(u=le(u).floor,A.current={...t,detachedSign:void 0,moved:!0}):A.current={...t,moved:!0},_r(u,`move-wall`,!1,[t.wallId]);return}if(t.kind===`opening`){let e=N.openings[t.openingId];if(!e)return;let r=N.walls[e.wallId],i=N.nodes[r.a],a=N.nodes[r.b],o=Math.hypot(a.x-i.x,a.y-i.y),s=((n.x-i.x)*(a.x-i.x)+(n.y-i.y)*(a.y-i.y))/(o*o||1);A.current={...t,moved:!0},_r(ce(N,t.openingId,{offset:Math.min(Math.max(s,0),1)*o}).floor,`move-opening`,!1,[t.openingId]);return}if(t.kind===`room`){let e=n.x-t.startWorld.x,r=n.y-t.startWorld.y,i=Vt!==wn.current&&C>0?C:1,a=Math.round(e/i)*i,o=Math.round(r/i)*i,s=N;for(let e of t.nodeIds){let n=t.orig[e];n&&(s=ie(s,e,{x:n.x+a,y:n.y+o}).floor)}A.current={...t,moved:!0},_r(s,`move-room`,!1,t.nodeIds)}}},[w,q,F,N,P,Un,k,B.zoom,Lt,Rt,C,Vt,pr,Y,_r,V,R,U,fr,Nt,lr]),Dr=m((e,t)=>{xn.current.delete(e.pointerId);let n=A.current;A.current={kind:`none`};let r=Sn.current?.moved??!1;if(Sn.current=null,rr(null),n.kind===`none`||n.kind===`pan`||n.kind===`pinch`)return;if(n.kind===`marquee`){if(t||!r){t&&R([...n.base]);return}let e=Math.min(n.start.x,n.current.x),i=Math.max(n.start.x,n.current.x),a=Math.min(n.start.y,n.current.y),o=Math.max(n.start.y,n.current.y),s=[];for(let t of Object.values(N.nodes))t.x>=e&&t.x<=i&&t.y>=a&&t.y<=o&&s.push({type:`node`,id:t.id});if(n.additive){let e=new Set(n.base.map(e=>`${e.type}:${e.id}`));R([...n.base,...s.filter(t=>!e.has(`${t.type}:${t.id}`))])}else R(s);return}if(t){let e=j.cancelGesture();e&&S?.(e,{reason:`external`,committed:!1,targetIds:[]});return}if(n.kind===`measureEnd`||n.kind===`measureMove`)return;if(n.kind===`measure`){let e=Math.hypot(n.current.x-n.start.x,n.current.y-n.start.y);r&&e>ft&&(ar.current+=1,ir(e=>[...e,{id:ar.current,a:n.start,b:n.current}]));return}if(n.kind===`rect`){if(!r){j.cancelGesture();return}let e=ee(N,n.start,n.current,{thickness:Gt,type:o.Interior,height:Kt},d(k,B.zoom).node);if(e.result.wallIds.length===0){j.cancelGesture();return}let t=j.endGesture();X(e.floor,`draw-rect`,e.result.wallIds,{push:!t});return}if(!r){j.cancelGesture(),n.kind===`wall`&&n.toggle&&Bn({type:`wall`,id:n.wallId});return}if(n.kind===`node`){let e=N.nodes[n.nodeId];if(e){let t=d(k,B.zoom).node,r=Object.values(N.nodes).find(r=>r.id!==n.nodeId&&Math.hypot(r.x-e.x,r.y-e.y)<=t);if(r){let e=j.endGesture();X(re(N,r.id,n.nodeId).floor,`move-node`,[r.id],{push:!e}),R({type:`node`,id:r.id});return}}}let i=j.endGesture(),a=n.kind===`wall`?`move-wall`:n.kind===`opening`?`move-opening`:n.kind===`room`?`move-room`:`move-node`;X(N,a,[],{push:!i})},[N,j,k,B.zoom,Gt,Kt,X,R,Bn,S]);h(()=>{let e=vn.current;if(!e||w)return;function t(t){t.preventDefault();let n=e.getBoundingClientRect(),r=Math.exp(-t.deltaY*.002);V((()=>{let e=Or.current,i=Math.max(Lt,Math.min(Rt,e.zoom*r)),a=Oe(t.clientX,t.clientY,n,e);return{x:a.x-(t.clientX-n.left)/i,y:a.y-(t.clientY-n.top)/i,zoom:i}})())}return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[w,Lt,Rt,V]);let Or=g(B);Or.current=B;let kr=m(e=>{let t=Math.max(Lt,Math.min(Rt,B.zoom*e)),n={x:B.x+H.width/2/B.zoom,y:B.y+H.height/2/B.zoom};V({x:n.x-H.width/2/t,y:n.y-H.height/2/t,zoom:t})},[B,H,Lt,Rt,V]),Ar=m(()=>{if(an===`none`)return;let e=j.undo();e&&(bn.current=e,S?.(e,{reason:`undo`,committed:!0,targetIds:[]}),yt?.(e,{reason:`undo`,committed:!0,targetIds:[]}))},[an,j,S,yt]),jr=m(()=>{if(an===`none`)return;let e=j.redo();e&&(bn.current=e,S?.(e,{reason:`redo`,committed:!0,targetIds:[]}),yt?.(e,{reason:`redo`,committed:!0,targetIds:[]}))},[an,j,S,yt]),Mr=m(()=>{let e=P.filter(e=>e.roomId).map(e=>({type:`room`,id:e.roomId}));if(e.length>0){R(e);return}R(Object.keys(N.nodes).map(e=>({type:`node`,id:e})))},[P,N.nodes,R]),Nr=m((e,t)=>{if(!q||Hn.size===0)return;let n=C>0?C:100,r=Tn.current?n*10:n,i=N;for(let n of Hn){let a=i.nodes[n];a&&(i=ie(i,n,{x:a.x+e*r,y:a.y+t*r}).floor)}X(i,`nudge`,[...Hn])},[q,Hn,N,C,X]),Pr=m(e=>{if(w)return;let t=e.target;if(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement){e.key===`Escape`&&t.blur();return}if(e.key===`Shift`&&(Tn.current=!0),e.key===`Alt`&&(wn.current=!0),e.key===` `&&!Cn.current){Cn.current=!0,e.preventDefault();return}let n=e.metaKey||e.ctrlKey;if(n&&e.key.toLowerCase()===`z`){e.preventDefault(),e.shiftKey?jr():Ar();return}if(n&&e.key.toLowerCase()===`a`){e.preventDefault(),Mt&&Mr();return}if(n&&e.key.toLowerCase()===`y`){e.preventDefault(),jr();return}if(e.key===`Escape`){U.length>0?wr():K.length>0?ir([]):R(null);return}if(e.key===`Enter`&&F===`wall`){wr();return}if(e.key===`Delete`||e.key===`Backspace`){if(e.preventDefault(),F===`measure`){or!==null&&(ir(e=>e.filter(e=>e.id!==or)),sr(null));return}Cr();return}if(e.key===`+`||e.key===`=`){kr(1.25);return}if(e.key===`-`){kr(1/1.25);return}if(e.key===`0`){hr();return}if(e.key.startsWith(`Arrow`)){e.preventDefault();let t={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[e.key];t&&Nr(t[0],t[1]);return}let r=e.key.toLowerCase();if(r===`s`){Zn(e=>!e);return}if(r===`l`){$n(e=>!e);return}if(r===`g`){tr(e=>!e);return}let i=ct[e.key.toLowerCase()];i&&q&&Ot.includes(i)&&(Ln(i),wr())},[w,q,Ot,F,U,K.length,or,jr,Ar,R,wr,Cr,kr,hr,Nr,Ln,Mt,Mr]),Q=m((e,t,n)=>{bn.current=e,n?.resetHistory?(j.clearHistory(),j.replace(e)):j.commit(e,t);let r={reason:t,committed:!0,targetIds:[]};S?.(e,r),yt?.(e,r)},[j,S,yt]),Fr=m((e={})=>{let{plan:t,floor:n}=ue(M,{...e,index:he(M,N.id)+1});return Q(t,`add-floor`),Pn(n.id),n.id},[M,N.id,Q,Pn]),Ir=m(()=>{let{plan:e,floor:t}=de(M,N.id);return t?(Q(e,`duplicate-floor`),Pn(t.id),t.id):null},[M,N.id,Q,Pn]),Lr=m(e=>{let t=e??N.id,n=ve(M,t);if(n!==M&&(Q(n,`remove-floor`),t===N.id)){let e=he(M,t);Pn(n.floors[Math.max(0,e-1)].id)}},[M,N.id,Q,Pn]),Rr=m((e,t)=>{let n=_e(M,e,t);n!==M&&Q(n,`move-floor`)},[M,Q]),zr=m((e,t)=>{let n=xe(M,e,t);n!==M&&Q(n,`edit-floor`)},[M,Q]),Br=m((e,t)=>{let n=ye(M,e,t);n!==M&&Q(n,`rename-floor`)},[M,Q]),Vr=m(e=>{let t=(e??nn??M.name??``).trim()||`floor-plan`,n=URL.createObjectURL(new Blob([je(M)],{type:`application/json`})),r=document.createElement(`a`);r.href=n,r.download=t.endsWith(`.json`)?t:`${t}.json`,r.click(),setTimeout(()=>URL.revokeObjectURL(n),0)},[nn,M]),Hr=m(e=>{let t=Ae(e);return t.plan&&Q(t.plan,`import`),dr(t.plan&&t.issues.length===0?null:t.issues),rn?.(t),t},[rn,Q]),Ur=m(e=>{e.text().then(e=>Hr(e)).catch(e=>{let t=[`Could not read that file: ${e.message}`];dr(t),rn?.({plan:null,issues:t})})},[Hr,rn]),Wr=m(()=>ir([]),[]),Gr=m(e=>{e.key===`Shift`&&(Tn.current=!1),e.key===`Alt`&&(wn.current=!1),e.key===` `&&(Cn.current=!1)},[]);Ie(Fe,()=>({getPlan:()=>M,setPlan:(e,t)=>Q(e,`import`,t),clear:()=>Q(fe(),`clear`),getFloorId:()=>N.id,setFloorId:Pn,addFloor:e=>Fr(e),duplicateFloor:Ir,removeFloor:Lr,renameFloor:Br,moveFloor:Rr,setFloorHeight:zr,clearMeasurements:Wr,download:Vr,loadJson:Hr,undo:Ar,redo:jr,canUndo:()=>an!==`none`&&j.canUndo,canRedo:()=>an!==`none`&&j.canRedo,clearHistory:j.clearHistory,getSelection:()=>[...L.current],select:R,addToSelection:e=>{let t=Array.isArray(e)?e:[e],n=new Set(L.current.map(e=>`${e.type}:${e.id}`));R([...L.current,...t.filter(e=>!n.has(`${e.type}:${e.id}`))])},toggleSelection:Bn,selectAll:Mr,deleteSelection:Cr,getView:()=>B,setView:V,zoomBy:kr,fitToContent:hr,toWorld:pr,toScreen:J,getSvgElement:()=>yn.current}),[M,j,Q,N,Pn,Fr,Ir,Lr,Br,Rr,zr,Wr,Vr,Hr,Ar,jr,an,R,Bn,Mr,Cr,B,V,kr,hr,pr,J]);let $=A.current,Kr=Le(()=>{if(!q)return null;let e=[],t=[...K,...$.kind===`measure`?[{id:-1,a:$.start,b:$.current}]:[]];for(let n of t){let t=J(n.a),r=J(n.b),i=Math.hypot(n.b.x-n.a.x,n.b.y-n.a.y);if(i<ft)continue;let a=Math.atan2(n.b.y-n.a.y,n.b.x-n.a.x),o=-Math.sin(a)*5,s=Math.cos(a)*5,c={x:(t.x+r.x)/2,y:(t.y+r.y)/2};if(e.push(b(`g`,{className:v(p.roomDrawerMeasureLine,or===n.id&&p.roomDrawerMeasureLineHovered,D?.measureLine),children:[y(`line`,{x1:t.x,y1:t.y,x2:r.x,y2:r.y}),y(`line`,{x1:t.x-o,y1:t.y-s,x2:t.x+o,y2:t.y+s}),y(`line`,{x1:r.x-o,y1:r.y-s,x2:r.x+o,y2:r.y+s})]},`measure-${n.id}`)),F===`measure`&&n.id>=0)for(let[i,a]of[[`a`,t],[`b`,r]])e.push(y(`circle`,{className:p.roomDrawerMeasureGrip,cx:a.x,cy:a.y,r:4},`measure-grip-${n.id}-${i}`));e.push(y(`text`,{className:v(p.roomDrawerMeasure,D?.measureLine),x:c.x,y:c.y-8,textAnchor:`middle`,children:`${Yt(i)} · ${_t(a)}`},`measure-label-${n.id}`))}if(Wt&&G&&(G.guides.forEach((t,n)=>{let r=J(t.a),i=J(t.b);e.push(y(`line`,{className:v(p.roomDrawerGuide,t.kind===f.Angle&&p.roomDrawerGuideAngle),x1:r.x,y1:r.y,x2:i.x,y2:i.y},`guide-${n}`))}),G.kind!==f.None&&G.kind!==f.Grid)){let t=J(G.point);e.push(y(`rect`,{className:p.roomDrawerSnapMarker,x:t.x-4,y:t.y-4,width:8,height:8},`snap-marker`))}if($.kind===`rect`){let t=J($.start),n=J($.current),r=Math.min(t.x,n.x),i=Math.min(t.y,n.y),a=Math.max(t.x,n.x),o=Math.max(t.y,n.y);e.push(y(`rect`,{className:p.roomDrawerPreview,x:r,y:i,width:a-r,height:o-i},`rect-preview`));let s=Math.abs($.current.x-$.start.x),c=Math.abs($.current.y-$.start.y);Jt&&(s>0||c>0)&&(e.push(y(`text`,{className:p.roomDrawerMeasure,x:(r+a)/2,y:i-8,textAnchor:`middle`,children:Yt(s)},`rect-width`),y(`text`,{className:p.roomDrawerMeasure,x:r-8,y:(i+o)/2,textAnchor:`end`,dominantBaseline:`central`,children:Yt(c)},`rect-height`)),s>0&&c>0&&e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureSecondary),x:(r+a)/2,y:(i+o)/2,textAnchor:`middle`,dominantBaseline:`central`,children:Xt(s*c)},`rect-area`)))}if(F===`wall`&&U.length>0){let t=[...U,W].filter(Boolean).map(J);if(e.push(y(`polyline`,{className:p.roomDrawerPreview,points:t.map(e=>`${e.x},${e.y}`).join(` `),fill:`none`},`chain`)),t.forEach((t,n)=>{e.push(y(`circle`,{className:p.roomDrawerHandle,cx:t.x,cy:t.y,r:4},`chain-dot-${n}`))}),Jt&&W&&U.length>0){let t=U[U.length-1],n=Math.hypot(W.x-t.x,W.y-t.y),r=J({x:(t.x+W.x)/2,y:(t.y+W.y)/2}),i=G?.kind===f.Angle;e.push(y(`text`,{className:v(p.roomDrawerMeasure,i&&p.roomDrawerMeasureLocked),x:r.x,y:r.y-8,textAnchor:`middle`,children:`${Yt(n)} · ${_t(G?.angleRelativeTo===`reference`&&fr!==void 0?Math.atan2(W.y-t.y,W.x-t.x)-fr:Math.atan2(W.y-t.y,W.x-t.x))}${G?.angleRelativeTo===`reference`?` rel`:``}`},`chain-len`))}}let n=new Set(I.filter(e=>e.type===`node`).map(e=>e.id));for(let t of Hn){let r=N.nodes[t];if(!r)continue;let i=J(r);e.push(y(`circle`,{className:v(p.roomDrawerHandle,n.has(t)&&p.roomDrawerHandleActive),cx:i.x,cy:i.y,r:5},`handle-${t}`))}if($.kind===`marquee`&&Sn.current?.moved){let t=J($.start),n=J($.current);e.push(y(`rect`,{className:p.roomDrawerMarquee,x:Math.min(t.x,n.x),y:Math.min(t.y,n.y),width:Math.abs(n.x-t.x),height:Math.abs(n.y-t.y)},`marquee`))}if(br&&$.kind!==`node`){let t=J(br);e.push(y(`circle`,{className:p.roomDrawerMidHandle,cx:t.x,cy:t.y,r:4},`midpoint`))}if(Jt&&$.kind===`room`&&$.moved){let t=new Set($.nodeIds),n=$.nodeIds.find(e=>N.nodes[e]&&$.orig[e]);if(n){let t=N.nodes[n],r=$.orig[n],i=t.x-r.x,a=t.y-r.y,o=z?.type===`room`?P.find(e=>e.roomId===z.id):void 0,s=J(o?o.anchor:t);e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureOffset),x:s.x,y:s.y-26,textAnchor:`middle`,children:`${Yt(Math.hypot(i,a))} · ${_t(Math.atan2(a,i))}`},`room-offset`))}for(let n of Object.values(N.walls)){if(t.has(n.a)===t.has(n.b))continue;let r=N.nodes[n.a],i=N.nodes[n.b];if(!r||!i)continue;let a=t.has(n.a)?r:i,o=t.has(n.a)?i:r,s=J({x:(r.x+i.x)/2,y:(r.y+i.y)/2});e.push(y(`text`,{className:v(p.roomDrawerMeasure,p.roomDrawerMeasureSecondary),x:s.x,y:s.y-8,textAnchor:`middle`,children:`${Yt(Math.hypot(o.x-a.x,o.y-a.y))} · ${_t(Math.atan2(o.y-a.y,o.x-a.x))}`},`room-stretch-${n.id}`))}}if(Jt&&(z?.type===`node`||z?.type===`wall`)){let t=[],n=new Set,r=(e,r,i)=>{if(n.has(e))return;let a=N.walls[e];a&&(n.add(e),t.push({wall:a,from:r,primary:i}))};if(z.type===`node`)for(let e of Object.values(N.walls))(e.a===z.id||e.b===z.id)&&r(e.id,z.id,!0);else{let e=N.walls[z.id];if(e){r(e.id,e.a,!0);for(let t of Object.values(N.walls))if(t.id!==e.id)for(let n of[e.a,e.b])(t.a===n||t.b===n)&&r(t.id,n,!1)}}let i=G?.kind===f.Angle&&$.kind!==`none`;for(let{wall:n,from:r,primary:a}of t){let t=N.nodes[n.a],o=N.nodes[n.b];if(!t||!o)continue;let s=n.a===r?t:o,c=n.a===r?o:t,l=J({x:(t.x+o.x)/2,y:(t.y+o.y)/2});e.push(y(`text`,{className:v(p.roomDrawerMeasure,!a&&p.roomDrawerMeasureSecondary,a&&i&&p.roomDrawerMeasureLocked),x:l.x,y:l.y-8,textAnchor:`middle`,children:`${Yt(Math.hypot(c.x-s.x,c.y-s.y))} · ${_t(Math.atan2(c.y-s.y,c.x-s.x))}`},`measure-${n.id}`))}}return y(ot,{children:e})},[q,$,F,U,W,I,N,P,z,Hn,br,Jt,Wt,G,fr,Yt,Xt,K,or,D?.measureLine,J]),qr={select:{icon:Be,label:T?.select??`Select and edit`,key:`V`},wall:{icon:$e,label:T?.wall??`Draw walls`,key:`W`},rect:{icon:nt,label:T?.rect??`Draw a room`,key:`R`},door:{icon:Ge,label:T?.door??`Add a door`,key:`D`},window:{icon:at,label:T?.window??`Add a window`,key:`N`},archway:{icon:Je,label:T?.archway??`Add an archway`,key:`A`},measure:{icon:tt,label:T?.measure??`Measure`,key:`M`}},Jr=q?F===`wall`?T?.hintWall??`Click to place corners · Shift for a fixed angle, L to latch it · Click the first corner or press Enter to close`:F===`rect`?T?.hintRect??`Drag to draw a room`:F===`measure`?T?.hintMeasure??`Drag to measure · Drag an end or the line to adjust it · Delete removes one, Escape clears them`:lt[F]?T?.hintOpening??`Click a wall to cut an opening into it`:T?.hintSelect??(Mt?`Drag a corner to reshape · Drag a wall to push it, and the room next door moves with it · Ctrl-click or drag a box to select several · Delete to remove`:`Drag a corner to reshape · Drag a wall to push it, and the room next door moves with it · Drag the dot on a selected wall to add a corner · Delete to remove`):``,Yr=I.length===0?T?.selectedFloor??`Floor`:I.length>1?(T?.selectedCount??`{count} selected`).replace(`{count}`,String(I.length)):yr?T?.selectedOpening??ut[yr.kind]:Z?T?.selectedWall??`Wall`:z?.type===`room`?T?.selectedRoom??`Room`:T?.selectedCorner??`Corner`,Xr=q?Ot:[];return b(`div`,{...hn,ref:_n,className:v(p.roomDrawer,w&&p.roomDrawerDisabled,pn,D?.root),style:{...mn,...O?.root},role:`application`,"aria-label":fn??`Floor plan editor`,tabIndex:w?-1:0,onKeyDown:Pr,onKeyUp:Gr,children:[Zt&&b(`div`,{className:v(p.roomDrawerToolbar,D?.toolbar),style:O?.toolbar,role:`toolbar`,"aria-label":T?.tools??`Drawing tools`,children:[Xr.map(e=>{let n=qr[e];return y(`button`,{type:`button`,className:v(p.roomDrawerToolButton,e===F&&p.roomDrawerToolButtonActive,D?.toolButton),style:O?.toolButton,title:`${n.label} (${n.key})`,"aria-label":n.label,"aria-pressed":e===F,onClick:()=>{Ln(e),wr()},children:t(E?.[e]??n.icon,{className:v(p.roomDrawerToolIcon,D?.toolIcon),style:O?.toolIcon})},e)}),Xr.length>0&&y(`span`,{className:p.roomDrawerToolbarSeparator}),q&&b(ot,{children:[[{on:Xn,toggle:()=>Zn(e=>!e),icon:E?.snap??Xe,label:T?.snap??`Snap to grid and geometry`,key:`S`},{on:Qn,toggle:()=>$n(e=>!e),icon:E?.angleLock??qe,label:T?.angleLock??`Lock to ${Ut}° angles`,key:`L`},{on:er,toggle:()=>tr(e=>!e),icon:E?.grid??Ue,label:T?.grid??`Show grid`,key:`G`},...pe(M,N.id)?[{on:jn,toggle:()=>Mn(e=>!e),icon:E?.underlay??Ye,label:T?.underlay??`Show the floor below`,key:`B`}]:[]].map(e=>y(`button`,{type:`button`,className:v(p.roomDrawerToolButton,e.on&&p.roomDrawerToolButtonOn,D?.toolButton),style:O?.toolButton,title:`${e.label} (${e.key})`,"aria-label":e.label,"aria-pressed":e.on,onClick:e.toggle,children:t(e.icon,{className:v(p.roomDrawerToolIcon,D?.toolIcon),style:O?.toolIcon})},e.key)),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),en&&an!==`none`&&q&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.undo??`Undo`,"aria-label":T?.undo??`Undo`,disabled:!j.canUndo,onClick:Ar,children:t(E?.undo??Ve)}),y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.redo??`Redo`,"aria-label":T?.redo??`Redo`,disabled:!j.canRedo,onClick:jr,children:t(E?.redo??He)}),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),tn&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.download??`Download plan`,"aria-label":T?.download??`Download plan`,onClick:()=>Vr(),children:t(E?.download??Ke)}),q&&y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.upload??`Open a plan file`,"aria-label":T?.upload??`Open a plan file`,onClick:()=>cr.current?.click(),children:t(E?.upload??it)}),y(`span`,{className:p.roomDrawerToolbarSeparator})]}),b(`div`,{className:v(p.roomDrawerViewControls,D?.viewControls),style:O?.viewControls,children:[y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.zoomOut??`Zoom out`,"aria-label":T?.zoomOut??`Zoom out`,onClick:()=>kr(1/1.25),children:t(E?.zoomOut??Ze)}),b(`button`,{type:`button`,className:v(p.roomDrawerZoomLabel,D?.zoomLabel),style:O?.zoomLabel,title:T?.fit??`Fit to content`,onClick:()=>hr(),children:[Math.round(B.zoom*1e3)/10,`%`]}),y(`button`,{type:`button`,className:v(p.roomDrawerViewButton,D?.viewButton),style:O?.viewButton,title:T?.zoomIn??`Zoom in`,"aria-label":T?.zoomIn??`Zoom in`,onClick:()=>kr(1.25),children:t(E?.zoomIn??Qe)})]})]}),Ct&&M.floors.length>0&&b(`div`,{className:v(p.roomDrawerFloorBar,D?.floorBar),style:O?.floorBar,role:`tablist`,"aria-label":T?.selectedFloor??`Floor`,children:[[...M.floors].reverse().map(e=>y(`button`,{type:`button`,role:`tab`,className:v(p.roomDrawerFloorTab,e.id===N.id&&p.roomDrawerFloorTabActive,D?.floorTab),style:O?.floorTab,"aria-selected":e.id===N.id,onClick:()=>Pn(e.id),children:e.label},e.id)),q&&y(`button`,{type:`button`,className:v(p.roomDrawerFloorTab,p.roomDrawerFloorTabAdd),title:T?.addFloor??`Add a floor above`,"aria-label":T?.addFloor??`Add a floor above`,onClick:()=>Fr(),children:t(E?.addFloor??et)})]}),y(`div`,{ref:vn,className:v(p.roomDrawerCanvasWrapper,q&&F!==`select`&&p.roomDrawerCanvasWrapperDrawing,D?.canvasWrapper),style:{height:ln,...O?.canvasWrapper},onPointerDown:Tr,onPointerMove:Er,onPointerUp:e=>Dr(e,!1),onPointerCancel:e=>Dr(e,!0),children:y(Ne,{ref:yn,floor:N,underlay:Nn,rooms:P,view:B,size:H,selection:I,hovered:Un,interactiveRooms:!1,showGrid:er,gridSize:C,showRoomLabels:!0,formatArea:Xt,getRoomColor:un,renderRoomLabel:dn,overlay:Kr,classNames:D,styles:O})}),Qt&&q&&b(`div`,{className:v(p.roomDrawerInspector,D?.inspector),style:O?.inspector,children:[y(`span`,{className:v(p.roomDrawerInspectorKind,I.length===0&&p.roomDrawerInspectorKindEmpty,D?.inspectorLabel),children:Yr}),I.length===0&&b(ot,{children:[y(i,{className:v(p.roomDrawerInspectorName,D?.inspectorField),style:O?.inspectorField,label:T?.floorName??`Floor name`,value:N.label,onChange:e=>Br(N.id,e)}),y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.floorHeight??`Height (mm)`,title:T?.storeyHeightHint??`Storey height. The floors above move to sit on top of it.`,value:N.height,decimalScale:0,min:500,step:100,showArrows:!0,onChange:e=>{e!==void 0&&zr(N.id,e)}}),M.floors.length>1&&b(ot,{children:[y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.moveFloorUp??`Move this floor up`,"aria-label":T?.moveFloorUp??`Move this floor up`,disabled:he(M,N.id)>=M.floors.length-1,onClick:()=>Rr(N.id,he(M,N.id)+1),children:t(E?.moveFloorUp??ze)}),y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.moveFloorDown??`Move this floor down`,"aria-label":T?.moveFloorDown??`Move this floor down`,disabled:he(M,N.id)<=0,onClick:()=>Rr(N.id,he(M,N.id)-1),children:t(E?.moveFloorDown??Re)})]}),y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,title:T?.duplicateFloor??`Copy this floor to a new one above`,onClick:()=>Ir(),children:t(E?.duplicateFloor??We)}),M.floors.length>1&&y(n,{className:p.roomDrawerInspectorDelete,icon:E?.delete??rt,title:T?.deleteFloor??`Delete this floor`,onClick:()=>Lr()})]}),vr?.meta&&b(ot,{children:[y(i,{className:v(p.roomDrawerInspectorName,D?.inspectorField),style:O?.inspectorField,label:T?.roomName??`Room name`,value:vr.meta.name,onChange:e=>{let t=vr.meta;X({...N,rooms:{...N.rooms,[t.id]:{...t,name:e}}},`edit-room`,[t.id])}}),y(`span`,{className:v(p.roomDrawerInspectorLabel,D?.inspectorLabel),children:Xt(vr.area)})]}),Z&&y(`button`,{type:`button`,className:v(p.roomDrawerInspectorAction,D?.inspectorField),style:O?.inspectorField,onClick:xr,title:T?.addCorner??`Add a corner to this wall`,children:T?.addCorner??`Add corner`}),Z&&y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.thickness??`Thickness (mm)`,value:Z.thickness,decimalScale:0,min:10,showArrows:!0,step:10,onChange:e=>{e!==void 0&&X({...N,walls:{...N.walls,[Z.id]:{...Z,thickness:e}}},`edit-wall`,[Z.id])}}),yr&&b(ot,{children:[y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.width??`Width (mm)`,value:yr.width,decimalScale:0,min:100,step:50,showArrows:!0,onChange:e=>{e!==void 0&&X(ce(N,yr.id,{width:e}).floor,`edit-opening`,[yr.id])}}),y(Me,{className:v(p.roomDrawerInspectorField,D?.inspectorField),style:O?.inspectorField,label:T?.sill??`Sill (mm)`,title:T?.sillHeightHint??`How far above the floor the opening starts. Stored for a 3D view; it does not change the plan.`,showArrows:!0,value:yr.sill,decimalScale:0,min:0,step:50,onChange:e=>{e!==void 0&&X(ce(N,yr.id,{sill:e}).floor,`edit-opening`,[yr.id])}})]}),I.length>0&&y(n,{className:p.roomDrawerInspectorDelete,icon:E?.delete??rt,title:T?.deleteSelection??`Delete selection`,onClick:Cr})]}),tn&&q&&y(`input`,{ref:cr,type:`file`,accept:`application/json,.json`,className:p.roomDrawerFileInput,tabIndex:-1,"aria-hidden":`true`,onChange:e=>{let t=e.target.files?.[0];e.target.value=``,t&&Ur(t)}}),$t&&(ur!==null||Jr)&&y(`div`,{className:v(p.roomDrawerHint,ur!==null&&p.roomDrawerHintReport,D?.hint),style:O?.hint,role:ur===null?void 0:`status`,children:ur===null?Jr:ur.length===0?T?.importFailed??`That file could not be read as a floor plan`:ur.join(` · `)})]})});export{x as default};
2
2
  //# sourceMappingURL=roomDrawer.mjs.map