@ahrowe/ui 0.19.1 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/common/colorPicker/colorPicker.module.mjs.map +1 -1
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs.map +1 -1
- package/dist/esm/common/datePicker/dateFunctions.mjs +1 -1
- package/dist/esm/common/datePicker/dateFunctions.mjs.map +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs.map +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs +1 -1
- package/dist/esm/common/floatingMenu/useFloatingPosition.mjs.map +1 -1
- package/dist/esm/common/hooks/useVisualViewportSize.mjs +2 -0
- package/dist/esm/common/hooks/useVisualViewportSize.mjs.map +1 -0
- package/dist/esm/common/inputDropdown/inputDropdown.mjs +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.mjs.map +1 -1
- package/dist/esm/common/inputDropdown/inputDropdown.module.mjs.map +1 -1
- package/dist/esm/common/modal/modal.mjs +1 -1
- package/dist/esm/common/modal/modal.mjs.map +1 -1
- package/dist/esm/common/modal/modal.module.mjs.map +1 -1
- package/dist/esm/common/optionPicker/optionPicker.module.mjs.map +1 -1
- package/dist/esm/common/popover/usePopoverPosition.mjs +1 -1
- package/dist/esm/common/popover/usePopoverPosition.mjs.map +1 -1
- package/dist/esm/common/themeProvider/defaultTheme.mjs +1 -1
- package/dist/esm/common/themeProvider/defaultTheme.mjs.map +1 -1
- package/dist/esm/common/utils/visualViewport.mjs +2 -0
- package/dist/esm/common/utils/visualViewport.mjs.map +1 -0
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/datePicker/components/datePickerMonth/datePickerMonth.d.ts +3 -1
- package/dist/types/package/common/datePicker/dateFunctions.d.ts +11 -0
- package/dist/types/package/common/hooks/useVisualViewportSize.d.ts +13 -0
- package/dist/types/package/common/themeProvider/theme.types.d.ts +1 -0
- package/dist/types/package/common/utils/visualViewport.d.ts +7 -0
- package/docs/DatePicker.md +2 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputDropdown.module.mjs","names":[],"sources":["../../../../package/common/inputDropdown/inputDropdown.module.pcss"],"sourcesContent":[".inputDropdown {\n position: relative;\n}\n\n.dropdown {\n position: fixed;\n width: fit-content;\n max-width:
|
|
1
|
+
{"version":3,"file":"inputDropdown.module.mjs","names":[],"sources":["../../../../package/common/inputDropdown/inputDropdown.module.pcss"],"sourcesContent":[".inputDropdown {\n position: relative;\n}\n\n.dropdown {\n position: fixed;\n width: fit-content;\n max-width: 15em;\n color: var(--text-color);\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n box-shadow: var(--card-shadow);\n box-sizing: border-box;\n overflow: hidden;\n transition: opacity 0.1s, transform 0.1s;\n transform-origin: top left;\n opacity: 0;\n transform: scale(0.95);\n z-index: 1;\n\n &-scroll {\n overflow: auto;\n max-height: 12.5em;\n }\n\n &-shown {\n transform: scale(1);\n opacity: 1;\n }\n\n &-flip {\n transform-origin: bottom left;\n }\n\n &-item {\n padding: 0.5em;\n z-index: 0;\n outline: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover,\n &:focus {\n background: var(--background-accent);\n }\n\n &-highlighted {\n background: var(--background-accent);\n }\n }\n\n &-category {\n padding: 1em 0.5em 0.25em 0.5em;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../bodyEnd/bodyEnd.mjs";import t from"./modal.module.mjs";import{useEffect as
|
|
1
|
+
import e from"../bodyEnd/bodyEnd.mjs";import t from"./modal.module.mjs";import{useVisualViewportSize as n}from"../hooks/useVisualViewportSize.mjs";import{useEffect as r,useState as i}from"react";import a from"classnames";import{FontAwesomeIcon as o}from"@fortawesome/react-fontawesome";import{faXmark as s}from"@fortawesome/free-solid-svg-icons";import{jsx as c,jsxs as l}from"react/jsx-runtime";function u({children:u=null,title:d=``,isOpen:f=!1,onClose:p=()=>null,className:m=``,style:h,hideHeader:g=!1,classNames:_,styles:v}){let[y,b]=i(f),[x,S]=i(f),{height:C,offsetTop:w}=n();return r(()=>{f?(b(f),setTimeout(()=>S(!0),1)):(S(!1),setTimeout(()=>b(f),300))},[f]),y?c(e,{children:l(`div`,{className:a(t.modalContainer,_?.container),style:{height:C,top:w,...v?.container},children:[c(`div`,{className:a(t.modalWrapper,x&&t.modalWrapperShown,_?.backdrop),style:v?.backdrop,onClick:p}),x&&l(`div`,{className:a(t.modal,x&&t.modalShown,m,_?.modal),style:{...h,...v?.modal},onClick:e=>e.stopPropagation(),children:[!g&&l(`div`,{className:a(t.modalHeader,_?.header),style:v?.header,children:[c(`div`,{className:_?.title,style:v?.title,children:d}),c(o,{onClick:p,icon:s,className:_?.closeButton,style:v?.closeButton})]}),u]})]})}):null}export{u as default};
|
|
2
2
|
//# sourceMappingURL=modal.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.mjs","names":[],"sources":["../../../../package/common/modal/modal.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './modal.module.pcss';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faXmark as closeIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ModalProps } from './modal.types';\nimport { useEffect, useState } from 'react';\n\nfunction Modal({\n children = null,\n title = '',\n isOpen = false,\n onClose = () => null,\n className = '',\n style,\n hideHeader = false,\n classNames,\n styles: slotStyles,\n}: ModalProps) {\n const [isRendered, setIsRendered] = useState(isOpen);\n const [animateIn, setAnimateIn] = useState(isOpen);\n\n useEffect(() => {\n if (isOpen) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsRendered(isOpen);\n setTimeout(() => setAnimateIn(true), 1);\n } else {\n setAnimateIn(false);\n setTimeout(() => setIsRendered(isOpen), 300);\n }\n }, [isOpen]);\n\n if (!isRendered) return null;\n\n return (\n <BodyEnd>\n <div
|
|
1
|
+
{"version":3,"file":"modal.mjs","names":[],"sources":["../../../../package/common/modal/modal.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport BodyEnd from 'components/common/bodyEnd';\n\nimport styles from './modal.module.pcss';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faXmark as closeIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ModalProps } from './modal.types';\nimport { useEffect, useState } from 'react';\nimport { useVisualViewportSize } from 'components/common/hooks/useVisualViewportSize';\n\nfunction Modal({\n children = null,\n title = '',\n isOpen = false,\n onClose = () => null,\n className = '',\n style,\n hideHeader = false,\n classNames,\n styles: slotStyles,\n}: ModalProps) {\n const [isRendered, setIsRendered] = useState(isOpen);\n const [animateIn, setAnimateIn] = useState(isOpen);\n // Centering/sizing against the actually-visible viewport (not the full layout viewport) keeps\n // the modal — and whatever's focused inside it — from ending up under a mobile keyboard.\n const { height: viewportHeight, offsetTop: viewportOffsetTop } = useVisualViewportSize();\n\n useEffect(() => {\n if (isOpen) {\n // eslint-disable-next-line react-hooks/set-state-in-effect\n setIsRendered(isOpen);\n setTimeout(() => setAnimateIn(true), 1);\n } else {\n setAnimateIn(false);\n setTimeout(() => setIsRendered(isOpen), 300);\n }\n }, [isOpen]);\n\n if (!isRendered) return null;\n\n return (\n <BodyEnd>\n <div\n className={cx(styles.modalContainer, classNames?.container)}\n style={{ height: viewportHeight, top: viewportOffsetTop, ...slotStyles?.container }}\n >\n <div\n className={cx(styles.modalWrapper, animateIn && styles.modalWrapperShown, classNames?.backdrop)}\n style={slotStyles?.backdrop}\n onClick={onClose}\n />\n {animateIn && (\n <div\n className={cx(styles.modal, animateIn && styles.modalShown, className, classNames?.modal)}\n style={{ ...style, ...slotStyles?.modal }}\n onClick={(e) => e.stopPropagation()}\n >\n {!hideHeader && (\n <div className={cx(styles.modalHeader, classNames?.header)} style={slotStyles?.header}>\n <div className={classNames?.title} style={slotStyles?.title}>{title}</div>\n <FontAwesomeIcon onClick={onClose} icon={closeIcon} className={classNames?.closeButton} style={slotStyles?.closeButton as React.CSSProperties & Record<`--fa-font-${string}`, string>} />\n </div>\n )}\n {children}\n </div>\n )}\n </div>\n </BodyEnd>\n );\n}\n\nexport default Modal;\n"],"mappings":"4YAWA,SAAS,EAAM,CACb,WAAW,KACX,QAAQ,GACR,SAAS,GACT,cAAgB,KAChB,YAAY,GACZ,QACA,aAAa,GACb,aACA,OAAQ,GACK,CACb,GAAM,CAAC,EAAY,GAAiB,EAAS,CAAM,EAC7C,CAAC,EAAW,GAAgB,EAAS,CAAM,EAG3C,CAAE,OAAQ,EAAgB,UAAW,GAAsB,EAAsB,EAevF,OAbA,MAAgB,CACV,GAEF,EAAc,CAAM,EACpB,eAAiB,EAAa,EAAI,EAAG,CAAC,IAEtC,EAAa,EAAK,EAClB,eAAiB,EAAc,CAAM,EAAG,GAAG,EAE/C,EAAG,CAAC,CAAM,CAAC,EAEN,EAGH,EAAC,EAAD,CAAA,SACE,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,eAAgB,GAAY,SAAS,EAC1D,MAAO,CAAE,OAAQ,EAAgB,IAAK,EAAmB,GAAG,GAAY,SAAU,WAFpF,CAIE,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,aAAc,GAAa,EAAO,kBAAmB,GAAY,QAAQ,EAC9F,MAAO,GAAY,SACnB,QAAS,CACV,CAAA,EACA,GACC,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,MAAO,GAAa,EAAO,WAAY,EAAW,GAAY,KAAK,EACxF,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,KAAM,EACxC,QAAU,GAAM,EAAE,gBAAgB,WAHpC,CAKG,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,YAAa,GAAY,MAAM,EAAG,MAAO,GAAY,gBAA/E,CACE,EAAC,MAAD,CAAK,UAAW,GAAY,MAAO,MAAO,GAAY,eAAQ,CAAW,CAAA,EACzE,EAAC,EAAD,CAAiB,QAAS,EAAS,KAAM,EAAW,UAAW,GAAY,YAAa,MAAO,GAAY,WAA6E,CAAA,CACrL,IAEN,CACE,GAEJ,GACE,CAAA,EA7Ba,IA+B1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.module.mjs","names":[],"sources":["../../../../package/common/modal/modal.module.pcss"],"sourcesContent":["\n.modal {\n padding: 16px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n position: relative;\n transform-origin: bottom center;\n animation:\n slideIn 0.2s,\n fadeIn 0.3s forwards;\n max-width: 95%;\n max-height: 95%;\n overflow: auto;\n\n @media not (--breakpoint-desktop) {\n max-width: 100%;\n max-height: 100%;\n }\n\n &-container {\n position:
|
|
1
|
+
{"version":3,"file":"modal.module.mjs","names":[],"sources":["../../../../package/common/modal/modal.module.pcss"],"sourcesContent":["\n.modal {\n padding: 16px;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-sizing: border-box;\n position: relative;\n transform-origin: bottom center;\n animation:\n slideIn 0.2s,\n fadeIn 0.3s forwards;\n max-width: 95%;\n max-height: 95%;\n overflow: auto;\n\n @media not (--breakpoint-desktop) {\n max-width: 100%;\n max-height: 100%;\n }\n\n &-container {\n position: fixed;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n top: 0;\n left: 0;\n }\n\n &-header {\n display: flex;\n gap: 8px;\n justify-content: space-between;\n margin-bottom: 16px;\n\n div {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n svg {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n }\n\n &-wrapper {\n position: fixed;\n width: 100%;\n height: 100%;\n background: #00000052;\n top: 0;\n left: 0;\n transition: all 0.3s ease-in-out;\n opacity: 0;\n\n &-shown {\n opacity: 1;\n }\n }\n}\n\n@keyframes slideIn {\n from {\n transform: scale(0);\n }\n to {\n transform: scale(0.99);\n }\n}\n\n@keyframes fadeIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optionPicker.module.mjs","names":[],"sources":["../../../../package/common/optionPicker/optionPicker.module.pcss"],"sourcesContent":[".optionPicker{\n display: flex;\n width: 100%;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n transition: border-color 0.15s;\n justify-content: space-around;\n position: relative;\n overflow: hidden;\n\n /* :has(:focus-visible) rather than :focus-within, so this only lights up on\n keyboard focus — same as the per-option ring below, not on a mouse click. */\n &:has(:focus-visible) {\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-chip {\n position: absolute;\n height: 100%;\n top: 0;\n left: 0;\n background: var(--primary-color);\n border-radius: var(--default-border-radius);\n transition: left 0.25s ease-in-out, width 0.25s ease-in-out;\n }\n\n &-option {\n position: relative;\n width: 100%;\n height: 100%;\n display: block;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: var(--spacing-m);\n overflow: hidden;\n text-overflow: ellipsis;\n border-radius: var(--default-border-radius);\n transition: color 0.25s;\n\n &:focus-visible {\n outline: var(--focus-border-color, var(--primary-color)) solid 2px;\n outline-offset: -2px;\n }\n\n &-active {\n color: var(--text-on-primary);\n\n /* The active option sits on the primary-color chip, so the default\n primary-color outline above is invisible against it — use the\n on-primary color instead, same as the option's own text/icon color. */\n &:focus-visible {\n outline-color: var(--text-on-primary);\n }\n }\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"optionPicker.module.mjs","names":[],"sources":["../../../../package/common/optionPicker/optionPicker.module.pcss"],"sourcesContent":[".optionPicker{\n display: flex;\n width: 100%;\n border-radius: var(--default-border-radius);\n border: 1px solid var(--border-color);\n transition: border-color 0.15s;\n justify-content: space-around;\n position: relative;\n overflow: hidden;\n\n /* :has(:focus-visible) rather than :focus-within, so this only lights up on\n keyboard focus — same as the per-option ring below, not on a mouse click. */\n &:has(:focus-visible) {\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-chip {\n position: absolute;\n height: 100%;\n top: 0;\n left: 0;\n background: var(--primary-color);\n border-radius: var(--default-border-radius);\n transition: left 0.25s ease-in-out, width 0.25s ease-in-out;\n }\n\n &-option {\n position: relative;\n width: 100%;\n height: 100%;\n display: block;\n align-content: center;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: var(--spacing-m);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n border-radius: var(--default-border-radius);\n transition: color 0.25s;\n box-sizing: border-box;\n\n &:focus-visible {\n outline: var(--focus-border-color, var(--primary-color)) solid 2px;\n outline-offset: -2px;\n }\n\n &-active {\n color: var(--text-on-primary);\n\n /* The active option sits on the primary-color chip, so the default\n primary-color outline above is invisible against it — use the\n on-primary color instead, same as the option's own text/icon color. */\n &:focus-visible {\n outline-color: var(--text-on-primary);\n }\n }\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{getScrollableAncestors as e,isHiddenByAnyAncestor as t}from"../utils/scrollAncestors.mjs";import{PopoverAlign as
|
|
1
|
+
import{getScrollableAncestors as e,isHiddenByAnyAncestor as t}from"../utils/scrollAncestors.mjs";import{getVisualViewportRect as n}from"../utils/visualViewport.mjs";import{PopoverAlign as r,PopoverPlacement as i}from"./popover.types.mjs";import{useLayoutEffect as a}from"react";var o={[i.Top]:`bottom`,[i.Bottom]:`top`,[i.Left]:`right`,[i.Right]:`left`},s=8;function c({isOpen:c,placement:l,align:u,offset:d,triggerRef:f,floatingRef:p,panelRef:m,arrowRef:h}){a(()=>{if(!c)return;let a,g;function _(){let c=f.current,v=p.current,y=m.current;if(!c||!v||!y){a=requestAnimationFrame(_);return}let b=e(c);function x(){let e=c.getBoundingClientRect(),a=y.offsetWidth,f=y.offsetHeight,p=n(),m={top:e.top-p.top,bottom:p.top+p.height-e.bottom,left:e.left-p.left,right:p.left+p.width-e.right},g=l===i.Top||l===i.Bottom?f:a,_=l,x=o[l];m[_]<g+d&&m[x]>m[_]&&(_=x);let S=_===`top`||_===`bottom`,C,w;_===`bottom`?C=e.bottom+d:_===`top`?C=e.top-d-f:w=_===`right`?e.right+d:e.left-d-a,S?(w=u===r.Start?e.left:u===r.End?e.right-a:e.left+e.width/2-a/2,w=Math.max(p.left+s,Math.min(w,p.left+p.width-a-s))):(C=u===r.Start?e.top:u===r.End?e.bottom-f:e.top+e.height/2-f/2,C=Math.max(p.top+s,Math.min(C,p.top+p.height-f-s))),v.style.top=`${C}px`,v.style.left=`${w}px`,v.style.visibility=t(e,b)?`hidden`:`visible`,v.dataset.placement=_;let T=h.current;if(T){let t=T.offsetWidth/2||5;if(S){let n=e.left+e.width/2-w;T.style.setProperty(`--arrow-x`,`${Math.max(t+2,Math.min(n,a-t-2))}px`),T.style.removeProperty(`--arrow-y`)}else{let n=e.top+e.height/2-C;T.style.setProperty(`--arrow-y`,`${Math.max(t+2,Math.min(n,f-t-2))}px`),T.style.removeProperty(`--arrow-x`)}}}x();let S=[window,...b];S.forEach(e=>e.addEventListener(`scroll`,x,{passive:!0})),window.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`resize`,x),window.visualViewport?.addEventListener(`scroll`,x),g=()=>{S.forEach(e=>e.removeEventListener(`scroll`,x)),window.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`resize`,x),window.visualViewport?.removeEventListener(`scroll`,x)}}return _(),()=>{a!==void 0&&cancelAnimationFrame(a),g?.()}},[c,l,u,d,f,p,m,h])}export{c as usePopoverPosition};
|
|
2
2
|
//# sourceMappingURL=usePopoverPosition.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopoverPosition.mjs","names":[],"sources":["../../../../package/common/popover/usePopoverPosition.ts"],"sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n
|
|
1
|
+
{"version":3,"file":"usePopoverPosition.mjs","names":[],"sources":["../../../../package/common/popover/usePopoverPosition.ts"],"sourcesContent":["import { useLayoutEffect, type RefObject } from 'react';\nimport { getScrollableAncestors, isHiddenByAnyAncestor } from 'components/common/utils/scrollAncestors';\nimport { getVisualViewportRect } from 'components/common/utils/visualViewport';\nimport { PopoverPlacement, PopoverAlign } from './popover.types';\n\ntype Axis = 'top' | 'bottom' | 'left' | 'right';\nconst OPPOSITE: Record<PopoverPlacement, Axis> = {\n [PopoverPlacement.Top]: 'bottom',\n [PopoverPlacement.Bottom]: 'top',\n [PopoverPlacement.Left]: 'right',\n [PopoverPlacement.Right]: 'left',\n};\n\nconst MARGIN = 8; // viewport gutter kept clear when shifting a panel back on-screen\n\nexport interface UsePopoverPositionArgs {\n isOpen: boolean;\n placement: PopoverPlacement;\n align: PopoverAlign;\n offset: number;\n triggerRef: RefObject<HTMLElement | null>;\n /** `position: fixed` wrapper that receives top/left/visibility and the resolved-placement data attribute. */\n floatingRef: RefObject<HTMLElement | null>;\n /** Visible panel, measured to decide flip and shift. */\n panelRef: RefObject<HTMLElement | null>;\n /** Arrow element; gets `--arrow-x` / `--arrow-y` written to it. Pass a null ref when `withArrow` is false. */\n arrowRef: RefObject<HTMLElement | null>;\n}\n\n/**\n * Positions a portaled, `position: fixed` popover on any of the four sides of its trigger with\n * start/center/end cross-axis alignment. Flips to the opposite side when the preferred one has no\n * room, shifts back on-screen along the cross axis, points the arrow at the trigger centre, and\n * hides (not closes) the panel once the trigger scrolls behind a clipping ancestor. Position is\n * written straight to the DOM via refs — going through setState lags the browser's scroll paint.\n */\nexport function usePopoverPosition({\n isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef,\n}: UsePopoverPositionArgs) {\n useLayoutEffect(() => {\n if (!isOpen) return;\n\n let rafId: number | undefined;\n let teardown: (() => void) | undefined;\n\n // The portal target (BodyEnd's #bodyEnd) can still be missing on the first commit, so the\n // floating ref lands one render later. Refs don't re-fire the effect, so retry each frame.\n function trySetup() {\n const trigger = triggerRef.current;\n const floating = floatingRef.current;\n const panel = panelRef.current;\n if (!trigger || !floating || !panel) {\n rafId = requestAnimationFrame(trySetup);\n return;\n }\n const ancestors = getScrollableAncestors(trigger);\n\n function updatePos() {\n const t = trigger!.getBoundingClientRect();\n const pw = panel!.offsetWidth;\n const ph = panel!.offsetHeight;\n // The visible area, not the full layout viewport — shrinks on mobile when a keyboard is\n // open, so the panel flips/clamps against what's actually on screen instead of ending up\n // hidden behind the keyboard.\n const vv = getVisualViewportRect();\n\n // Resolve the main-axis side, flipping when the preferred side lacks room and the\n // opposite side has more.\n const room: Record<Axis, number> = {\n top: t.top - vv.top,\n bottom: vv.top + vv.height - t.bottom,\n left: t.left - vv.left,\n right: vv.left + vv.width - t.right,\n };\n const need = (placement === PopoverPlacement.Top || placement === PopoverPlacement.Bottom) ? ph : pw;\n let side: Axis = placement as unknown as Axis;\n const opp = OPPOSITE[placement];\n if (room[side] < need + offset && room[opp] > room[side]) side = opp;\n\n const vertical = side === 'top' || side === 'bottom';\n\n // Main axis: place the panel just outside the trigger on the resolved side.\n let top: number;\n let left: number;\n if (side === 'bottom') { top = t.bottom + offset; }\n else if (side === 'top') { top = t.top - offset - ph; }\n else if (side === 'right') { left = t.right + offset; }\n else { left = t.left - offset - pw; }\n\n // Cross axis: align start/center/end against the trigger, then shift on-screen.\n if (vertical) {\n if (align === PopoverAlign.Start) left = t.left;\n else if (align === PopoverAlign.End) left = t.right - pw;\n else left = t.left + t.width / 2 - pw / 2;\n left = Math.max(vv.left + MARGIN, Math.min(left!, vv.left + vv.width - pw - MARGIN));\n } else {\n if (align === PopoverAlign.Start) top = t.top;\n else if (align === PopoverAlign.End) top = t.bottom - ph;\n else top = t.top + t.height / 2 - ph / 2;\n top = Math.max(vv.top + MARGIN, Math.min(top!, vv.top + vv.height - ph - MARGIN));\n }\n\n floating!.style.top = `${top!}px`;\n floating!.style.left = `${left!}px`;\n floating!.style.visibility = isHiddenByAnyAncestor(t, ancestors) ? 'hidden' : 'visible';\n floating!.dataset.placement = side;\n\n // Arrow: centre it on the trigger along the cross axis, clamped inside the panel edges.\n const arrow = arrowRef.current;\n if (arrow) {\n const half = arrow.offsetWidth / 2 || 5;\n if (vertical) {\n const x = t.left + t.width / 2 - left!;\n arrow.style.setProperty('--arrow-x', `${Math.max(half + 2, Math.min(x, pw - half - 2))}px`);\n arrow.style.removeProperty('--arrow-y');\n } else {\n const y = t.top + t.height / 2 - top!;\n arrow.style.setProperty('--arrow-y', `${Math.max(half + 2, Math.min(y, ph - half - 2))}px`);\n arrow.style.removeProperty('--arrow-x');\n }\n }\n }\n\n updatePos();\n\n const scrollTargets: (Window | HTMLElement)[] = [window, ...ancestors];\n scrollTargets.forEach((tt) => tt.addEventListener('scroll', updatePos, { passive: true }));\n window.addEventListener('resize', updatePos);\n // `window.resize` doesn't reliably fire when a mobile keyboard opens/closes — visualViewport\n // does, and is what the room/clamp math above is measured against.\n window.visualViewport?.addEventListener('resize', updatePos);\n window.visualViewport?.addEventListener('scroll', updatePos);\n teardown = () => {\n scrollTargets.forEach((tt) => tt.removeEventListener('scroll', updatePos));\n window.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('resize', updatePos);\n window.visualViewport?.removeEventListener('scroll', updatePos);\n };\n }\n\n trySetup();\n\n return () => {\n if (rafId !== undefined) cancelAnimationFrame(rafId);\n teardown?.();\n };\n }, [isOpen, placement, align, offset, triggerRef, floatingRef, panelRef, arrowRef]);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e={id:`default`,variables:{"--grey":`#8A8A8A`,"--lightgrey":`#e0e0e0`,"--lightergrey":`#B1B1B1`,"--white":`#FFFFFF`,"--red":`#D6002A`,"--lighter-red":`#ffeae9`,"--green":`#287626`,"--lighter-green":`#C4FFC9`,"--blue":`#5873d5`,"--lighter-blue":`#C6DBFF`,"--black":`black`,"--orange":`#ff7f50`,"--lighter-orange":`#ffe5d9`,"--primary-color":`#8184d6`,"--primary-accent":`#90CAF9`,"--primary-lighter":`#9a9ce4`,"--accent-color":`var(--grey)`,"--accent-color-light":`var(--lightgrey)`,"--text-color":`var(--white)`,"--text-dark":`var(--lightergrey)`,"--text-light":`var(--lightergrey)`,"--text-on-primary":`var(--white)`,"--text-on-delete":`var(--white)`,"--border-color":`#656574`,"--focus-border-color":`var(--primary-color)`,"--background":`#393945`,"--background-accent":`#33333c`,"--background-accent-dark":`var(--grey)`,"--background-accent-light":`#484856`,"--background-modal":`#484856`,"--success-color":`var(--green)`,"--success-lighter":`var(--lighter-green)`,"--error-color":`var(--red)`,"--error-lighter":`var(--lighter-red)`,"--required-mark-color":`var(--error-color)`,"--info-color":`var(--blue)`,"--info-lighter":`var(--lighter-blue)`,"--warn-color":`var(--orange)`,"--warn-lighter":`var(--lighter-orange)`,"--default-font-size":`
|
|
1
|
+
var e={id:`default`,variables:{"--grey":`#8A8A8A`,"--lightgrey":`#e0e0e0`,"--lightergrey":`#B1B1B1`,"--white":`#FFFFFF`,"--red":`#D6002A`,"--lighter-red":`#ffeae9`,"--green":`#287626`,"--lighter-green":`#C4FFC9`,"--blue":`#5873d5`,"--lighter-blue":`#C6DBFF`,"--black":`black`,"--orange":`#ff7f50`,"--lighter-orange":`#ffe5d9`,"--primary-color":`#8184d6`,"--primary-accent":`#90CAF9`,"--primary-lighter":`#9a9ce4`,"--accent-color":`var(--grey)`,"--accent-color-light":`var(--lightgrey)`,"--text-color":`var(--white)`,"--text-dark":`var(--lightergrey)`,"--text-light":`var(--lightergrey)`,"--text-on-primary":`var(--white)`,"--text-on-delete":`var(--white)`,"--border-color":`#656574`,"--focus-border-color":`var(--primary-color)`,"--background":`#393945`,"--background-accent":`#33333c`,"--background-accent-dark":`var(--grey)`,"--background-accent-light":`#484856`,"--background-modal":`#484856`,"--success-color":`var(--green)`,"--success-lighter":`var(--lighter-green)`,"--error-color":`var(--red)`,"--error-lighter":`var(--lighter-red)`,"--required-mark-color":`var(--error-color)`,"--info-color":`var(--blue)`,"--info-lighter":`var(--lighter-blue)`,"--warn-color":`var(--orange)`,"--warn-lighter":`var(--lighter-orange)`,"--default-font-size":`16px`,"--text-small-font-size":`14px`,"--header-font-size":`24px`,"--header-medium-font-size":`18px`,"--header-small-font-size":`16px`,"--default-font-weight":`400`,"--header-font-weight":`600`,"--input-background":`transparent`,"--input-icon-color":`var(--text-color)`,"--error-border-color":`var(--red)`,"--button-default-color":`var(--primary-color)`,"--button-default-border":`1px solid var(--primary-color)`,"--default-border-radius":`8px`,"--padding-sides":`15px`,"--margin-top":`10px`,"--default-font":`'Inter', sans-serif`,"--themed-font":`'Inter', sans-serif`,"--card-shadow":`0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)`,"--background-card-elevated":`var(--background-accent-light)`,"--background-card-outlined":`transparent`,"--background-card-filled":`var(--background-accent)`,"--spacing-s":`4px`,"--spacing-m":`8px`,"--spacing-l":`16px`}};export{e as defaultTheme};
|
|
2
2
|
//# sourceMappingURL=defaultTheme.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTheme.mjs","names":[],"sources":["../../../../package/common/themeProvider/defaultTheme.ts"],"sourcesContent":["import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n '--focus-border-color': 'var(--primary-color)',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '
|
|
1
|
+
{"version":3,"file":"defaultTheme.mjs","names":[],"sources":["../../../../package/common/themeProvider/defaultTheme.ts"],"sourcesContent":["import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n '--focus-border-color': 'var(--primary-color)',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '16px',\n '--text-small-font-size': '14px',\n '--header-font-size': '24px',\n '--header-medium-font-size': '18px',\n '--header-small-font-size': '16px',\n\n '--default-font-weight': '400',\n '--header-font-weight': '600',\n\n '--input-background': 'transparent',\n '--input-icon-color': 'var(--text-color)',\n '--error-border-color': 'var(--red)',\n\n '--button-default-color': 'var(--primary-color)',\n '--button-default-border': '1px solid var(--primary-color)',\n\n '--default-border-radius': '8px',\n '--padding-sides': '15px',\n '--margin-top': '10px',\n\n '--default-font': \"'Inter', sans-serif\",\n '--themed-font': \"'Inter', sans-serif\",\n\n '--card-shadow':\n '0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)',\n\n '--background-card-elevated': 'var(--background-accent-light)',\n '--background-card-outlined': 'transparent',\n '--background-card-filled': 'var(--background-accent)',\n\n '--spacing-s': '4px',\n '--spacing-m': '8px',\n '--spacing-l': '16px',\n },\n};\n"],"mappings":"AAOA,IAAa,EAAsB,CACjC,GAAI,UACJ,UAAW,CACT,SAAU,UACV,cAAe,UACf,gBAAiB,UACjB,UAAW,UACX,QAAS,UACT,gBAAiB,UACjB,UAAW,UACX,kBAAmB,UACnB,SAAU,UACV,iBAAkB,UAClB,UAAW,QACX,WAAY,UACZ,mBAAoB,UAEpB,kBAAmB,UACnB,mBAAoB,UACpB,oBAAqB,UACrB,iBAAkB,cAClB,uBAAwB,mBAExB,eAAgB,eAChB,cAAe,qBACf,eAAgB,qBAChB,oBAAqB,eACrB,mBAAoB,eACpB,iBAAkB,UAClB,uBAAwB,uBAExB,eAAgB,UAChB,sBAAuB,UACvB,2BAA4B,cAC5B,4BAA6B,UAC7B,qBAAsB,UAEtB,kBAAmB,eACnB,oBAAqB,uBACrB,gBAAiB,aACjB,kBAAmB,qBACnB,wBAAyB,qBACzB,eAAgB,cAChB,iBAAkB,sBAClB,eAAgB,gBAChB,iBAAkB,wBAElB,sBAAuB,OACvB,yBAA0B,OAC1B,qBAAsB,OACtB,4BAA6B,OAC7B,2BAA4B,OAE5B,wBAAyB,MACzB,uBAAwB,MAExB,qBAAsB,cACtB,qBAAsB,oBACtB,uBAAwB,aAExB,yBAA0B,uBAC1B,0BAA2B,iCAE3B,0BAA2B,MAC3B,kBAAmB,OACnB,eAAgB,OAEhB,iBAAkB,sBAClB,gBAAiB,sBAEjB,gBACE,8FAEF,6BAA8B,iCAC9B,6BAA8B,cAC9B,2BAA4B,2BAE5B,cAAe,MACf,cAAe,MACf,cAAe,MACjB,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(){let e=typeof window<`u`?window.visualViewport:null;return e?{left:e.offsetLeft,top:e.offsetTop,width:e.width,height:e.height}:{left:0,top:0,width:typeof window<`u`?window.innerWidth:0,height:typeof window<`u`?window.innerHeight:0}}export{e as getVisualViewportRect};
|
|
2
|
+
//# sourceMappingURL=visualViewport.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visualViewport.mjs","names":[],"sources":["../../../../package/common/utils/visualViewport.ts"],"sourcesContent":["export interface VisualViewportRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n// `window.visualViewport` reports the actually-visible area, which shrinks (and offsets) when a\n// mobile on-screen keyboard opens — unlike `window.innerWidth`/`innerHeight`, which stay pinned to\n// the full layout viewport. `getBoundingClientRect()` is relative to the layout viewport's origin,\n// so `left`/`top` here let callers translate into the same coordinate space before clamping.\nexport function getVisualViewportRect(): VisualViewportRect {\n const vv = typeof window !== 'undefined' ? window.visualViewport : null;\n if (vv) return { left: vv.offsetLeft, top: vv.offsetTop, width: vv.width, height: vv.height };\n return {\n left: 0,\n top: 0,\n width: typeof window !== 'undefined' ? window.innerWidth : 0,\n height: typeof window !== 'undefined' ? window.innerHeight : 0,\n };\n}\n"],"mappings":"AAWA,SAAgB,GAA4C,CAC1D,IAAM,EAAK,OAAO,OAAW,IAAc,OAAO,eAAiB,KAEnE,OADI,EAAW,CAAE,KAAM,EAAG,WAAY,IAAK,EAAG,UAAW,MAAO,EAAG,MAAO,OAAQ,EAAG,MAAO,EACrF,CACL,KAAM,EACN,IAAK,EACL,MAAO,OAAO,OAAW,IAAc,OAAO,WAAa,EAC3D,OAAQ,OAAO,OAAW,IAAc,OAAO,YAAc,CAC/D,CACF"}
|