@pk-design/react-tailwind 1.13.1 → 1.14.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.
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sources":["../../../../../src/components/Button/Button.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, useEffect, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport type { ButtonComponent, ButtonProps, ButtonSize, ThemedButtonClass } from './Button.types'\nimport type { PolymorphicRef } from '../common-type'\n\n/**\n * Tailwind CSS classes for theme + variant combinations.\n *\n * Only colours live here. Focus outline width/offset and disabled styling are\n * applied uniformly in the component so they can be toggled in one place.\n */\nconst THEMED_BTN_CLASS: ThemedButtonClass = {\n primary: {\n default:\n 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:outline-[var(--ui-primary-ring)]',\n outlined:\n 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:outline-[var(--ui-primary-ring)]',\n plain:\n 'text-[var(--ui-primary-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-primary-ring)]',\n },\n danger: {\n default:\n 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:outline-[var(--ui-danger-ring)]',\n outlined:\n 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:outline-[var(--ui-danger-ring)]',\n plain:\n 'text-[var(--ui-danger-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-danger-ring)]',\n },\n secondary: {\n default:\n 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:outline-[var(--ui-focus-ring)]',\n outlined:\n 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:outline-[var(--ui-focus-ring)]',\n plain:\n 'text-gray-700 hover:bg-current/10 active:bg-current/15 dark:text-gray-200 focus-visible:outline-[var(--ui-focus-ring)]',\n },\n success: {\n default: 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:outline-emerald-500',\n outlined:\n 'text-emerald-700 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:outline-emerald-500',\n plain:\n 'text-emerald-700 hover:bg-current/10 active:bg-current/15 dark:text-emerald-400 focus-visible:outline-emerald-500',\n },\n warning: {\n default: 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:outline-amber-500',\n outlined:\n 'text-amber-700 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:outline-amber-500',\n plain:\n 'text-amber-700 hover:bg-current/10 active:bg-current/15 dark:text-amber-400 focus-visible:outline-amber-500',\n },\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, { normal: string; iconOnly: string }> = {\n xs: { normal: 'h-7 px-2.5 rounded-sm gap-1 text-xs', iconOnly: 'h-7 w-7 p-1 rounded-sm text-xs' },\n sm: { normal: 'h-8 px-3 rounded gap-1.5 text-sm', iconOnly: 'h-8 w-8 p-1.5 rounded text-sm' },\n md: { normal: 'h-9 px-4 rounded-md gap-2 text-sm', iconOnly: 'h-9 w-9 p-2 rounded-md text-sm' },\n lg: {\n normal: 'h-10 px-5 rounded-lg gap-2 text-base',\n iconOnly: 'h-10 w-10 p-2.5 rounded-lg text-base',\n },\n}\n\nconst LOADER_SIZE: Record<ButtonSize, 'xs' | 'sm'> = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n lg: 'sm',\n}\n\n/**\n * Base shared tailwind classes.\n *\n * Disabled styling is keyed off both the native `disabled` attribute and\n * `aria-disabled`, so non-button elements rendered via `as` look disabled too.\n */\nconst BASE_BTN_CLASS =\n 'font-medium inline-flex items-center justify-center shrink-0 cursor-pointer select-none ' +\n 'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-150 ease-out ' +\n 'active:scale-[0.98] focus:outline-none ' +\n 'disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none ' +\n 'aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:shadow-none'\n\nexport const Button = forwardRef(\n <C extends ElementType = 'button'>(\n { as, type, ...props }: ButtonProps<C>,\n ref: PolymorphicRef<C>,\n ) => {\n const {\n className = '',\n children,\n theme = 'primary',\n variant = 'default',\n size = 'md',\n leftIcon,\n rightIcon,\n fullWidth = false,\n loading = false,\n loadingText = '',\n rounded = false,\n disabled,\n iconOnly = false,\n noOutlineOnFocus = false,\n active,\n onClick,\n ...restProps\n } = props\n\n const Component = as || 'button'\n const isNativeButton = Component === 'button'\n\n // Clean invalid props when not rendering a real button\n const {\n type: _ignoreType,\n disabled: _ignoreDisabled,\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n ...domProps\n } = restProps as Record<string, any>\n\n const ariaLabel = domProps['aria-label']\n const ariaLabelledBy = domProps['aria-labelledby']\n\n // Accessibility guard for icon-only buttons\n useEffect(() => {\n if (iconOnly && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[ui] <Button iconOnly> requires aria-label or aria-labelledby for accessibility.',\n )\n }\n }, [iconOnly, ariaLabel, ariaLabelledBy])\n\n const resolvedDisabled = Boolean(disabled || loading)\n\n // Links (`href`, or `to` for router Link components) keep their native semantics.\n const isLink = !isNativeButton && (domProps.href != null || domProps.to != null)\n\n const handleClick = (e: React.MouseEvent<any>) => {\n if (resolvedDisabled) {\n e.preventDefault()\n e.stopPropagation()\n return\n }\n onClick?.(e)\n }\n\n // Mirror native <button> keyboard activation for non-button elements:\n // Enter activates on keydown, Space on keyup (and must not scroll the page).\n const handleKeyDown = (e: React.KeyboardEvent<any>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === 'Enter') {\n e.preventDefault()\n e.currentTarget.click()\n } else if (e.key === ' ') {\n e.preventDefault()\n }\n }\n\n const handleKeyUp = (e: React.KeyboardEvent<any>) => {\n onKeyUp?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === ' ') {\n e.preventDefault()\n e.currentTarget.click()\n }\n }\n\n const elementProps = isNativeButton\n ? {\n type: type ?? 'button',\n disabled: resolvedDisabled,\n role,\n tabIndex,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : isLink\n ? {\n role,\n tabIndex: resolvedDisabled ? -1 : tabIndex,\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : {\n role: role ?? 'button',\n tabIndex: resolvedDisabled ? -1 : (tabIndex ?? 0),\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }\n\n const sizeObj = SIZE_CLASSES[size] || SIZE_CLASSES.md\n\n const classes = useMemo(\n () =>\n buildClassName(\n BASE_BTN_CLASS,\n THEMED_BTN_CLASS[theme]?.[variant] || THEMED_BTN_CLASS.primary.default,\n iconOnly ? sizeObj.iconOnly : sizeObj.normal,\n // An outline (not a ring) so the offset gap stays transparent on any surface/mode.\n !noOutlineOnFocus &&\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid',\n rounded && 'rounded-full',\n fullWidth && 'w-full',\n variant === 'default' && 'shadow-xs hover:shadow-none',\n active && 'ring-2 ring-current',\n className,\n ),\n [theme, variant, sizeObj, iconOnly, noOutlineOnFocus, rounded, fullWidth, active, className],\n )\n\n // The spinner and loading text inherit the button's text colour.\n const loaderIcon = (\n <Loader\n data-testid=\"btn-loader-icon\"\n size={LOADER_SIZE[size] || 'xs'}\n className=\"text-current\"\n />\n )\n\n /**\n * SPECIAL CASE: iconOnly + loading → show spinner only\n */\n if (loading && iconOnly) {\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy=\"true\"\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loaderIcon}\n </Component>\n )\n }\n\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy={loading ? 'true' : undefined}\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loading ? (\n <span className=\"inline-flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n {loadingText ? (\n <TextContent className=\"text-current\">{loadingText}</TextContent>\n ) : (\n children\n )}\n </span>\n ) : (\n <>\n {leftIcon && <span className=\"shrink-0 inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"shrink-0 inline-flex items-center\">{rightIcon}</span>}\n </>\n )}\n </Component>\n )\n },\n) as ButtonComponent\n\nButton.displayName = 'Button'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Button.js","sources":["../../../../../src/components/Button/Button.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, useEffect, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport type { ButtonComponent, ButtonProps, ButtonSize, ThemedButtonClass } from './Button.types'\nimport type { PolymorphicRef } from '../common-type'\n\n/**\n * Tailwind CSS classes for theme + variant combinations.\n *\n * Only colours live here. Focus outline width/offset and disabled styling are\n * applied uniformly in the component so they can be toggled in one place.\n */\nconst THEMED_BTN_CLASS: ThemedButtonClass = {\n primary: {\n default:\n 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:outline-[var(--ui-primary-ring)]',\n outlined:\n 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:outline-[var(--ui-primary-ring)]',\n plain:\n 'text-[var(--ui-primary-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-primary-ring)]',\n },\n danger: {\n default:\n 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:outline-[var(--ui-danger-ring)]',\n outlined:\n 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:outline-[var(--ui-danger-ring)]',\n plain:\n 'text-[var(--ui-danger-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-danger-ring)]',\n },\n secondary: {\n default:\n 'text-gray-800 bg-gray-200 hover:bg-gray-300 active:bg-gray-300 dark:text-white dark:bg-gray-700 dark:hover:bg-gray-600 dark:active:bg-gray-600 focus-visible:outline-[var(--ui-focus-ring)]',\n outlined:\n 'text-gray-800 bg-white border border-gray-300 shadow-xs hover:bg-gray-100 active:bg-gray-200 dark:text-gray-100 dark:bg-transparent dark:border-gray-600 dark:shadow-none dark:hover:bg-white/10 dark:active:bg-white/15 focus-visible:outline-[var(--ui-focus-ring)]',\n plain:\n 'text-gray-700 hover:bg-current/10 active:bg-current/15 dark:text-gray-200 focus-visible:outline-[var(--ui-focus-ring)]',\n },\n success: {\n default: 'text-white bg-emerald-700 hover:bg-emerald-800 focus-visible:outline-emerald-500',\n outlined:\n 'text-emerald-700 hover:text-white border border-emerald-700 hover:bg-emerald-700 dark:text-emerald-400 dark:border-emerald-500 focus-visible:outline-emerald-500',\n plain:\n 'text-emerald-700 hover:bg-current/10 active:bg-current/15 dark:text-emerald-400 focus-visible:outline-emerald-500',\n },\n warning: {\n default: 'text-gray-900 bg-amber-500 hover:bg-amber-400 focus-visible:outline-amber-500',\n outlined:\n 'text-amber-700 hover:text-gray-900 border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:outline-amber-500',\n plain:\n 'text-amber-700 hover:bg-current/10 active:bg-current/15 dark:text-amber-400 focus-visible:outline-amber-500',\n },\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, { normal: string; iconOnly: string }> = {\n xs: {\n normal: 'min-h-7 px-2.5 py-1 rounded-sm gap-1 text-xs',\n iconOnly: 'h-7 w-7 p-1 rounded-sm text-xs',\n },\n sm: {\n normal: 'min-h-8 px-3 py-1 rounded gap-1.5 text-sm',\n iconOnly: 'h-8 w-8 p-1.5 rounded text-sm',\n },\n md: {\n normal: 'min-h-9 px-4 py-1.5 rounded-md gap-2 text-sm',\n iconOnly: 'h-9 w-9 p-2 rounded-md text-sm',\n },\n lg: {\n normal: 'min-h-10 px-5 py-2 rounded-lg gap-2 text-base',\n iconOnly: 'h-10 w-10 p-2.5 rounded-lg text-base',\n },\n}\n\nconst LOADER_SIZE: Record<ButtonSize, 'xs' | 'sm'> = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n lg: 'sm',\n}\n\n/**\n * Base shared tailwind classes.\n *\n * Disabled styling is keyed off both the native `disabled` attribute and\n * `aria-disabled`, so non-button elements rendered via `as` look disabled too.\n *\n * On touch screens an invisible layer makes the tappable area at least 44px,\n * whatever the button's size, without changing how it looks.\n */\nconst BASE_BTN_CLASS =\n 'relative font-medium inline-flex items-center justify-center text-center shrink-0 cursor-pointer select-none ' +\n 'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-150 ease-out ' +\n 'active:scale-[0.98] focus:outline-none ' +\n 'disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none ' +\n 'aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:shadow-none ' +\n 'pointer-coarse:after:absolute pointer-coarse:after:top-1/2 pointer-coarse:after:left-1/2 ' +\n 'pointer-coarse:after:-translate-x-1/2 pointer-coarse:after:-translate-y-1/2 ' +\n 'pointer-coarse:after:w-full pointer-coarse:after:min-w-11 pointer-coarse:after:h-full pointer-coarse:after:min-h-11'\n\nexport const Button = forwardRef(\n <C extends ElementType = 'button'>(\n { as, type, ...props }: ButtonProps<C>,\n ref: PolymorphicRef<C>,\n ) => {\n const {\n className = '',\n children,\n theme = 'primary',\n variant = 'default',\n size = 'md',\n leftIcon,\n rightIcon,\n fullWidth = false,\n loading = false,\n loadingText = '',\n rounded = false,\n disabled,\n iconOnly = false,\n noOutlineOnFocus = false,\n active,\n onClick,\n ...restProps\n } = props\n\n const Component = as || 'button'\n const isNativeButton = Component === 'button'\n\n // Clean invalid props when not rendering a real button\n const {\n type: _ignoreType,\n disabled: _ignoreDisabled,\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n ...domProps\n } = restProps as Record<string, any>\n\n const ariaLabel = domProps['aria-label']\n const ariaLabelledBy = domProps['aria-labelledby']\n\n // Accessibility guard for icon-only buttons\n useEffect(() => {\n if (iconOnly && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[ui] <Button iconOnly> requires aria-label or aria-labelledby for accessibility.',\n )\n }\n }, [iconOnly, ariaLabel, ariaLabelledBy])\n\n const resolvedDisabled = Boolean(disabled || loading)\n\n // Links (`href`, or `to` for router Link components) keep their native semantics.\n const isLink = !isNativeButton && (domProps.href != null || domProps.to != null)\n\n const handleClick = (e: React.MouseEvent<any>) => {\n if (resolvedDisabled) {\n e.preventDefault()\n e.stopPropagation()\n return\n }\n onClick?.(e)\n }\n\n // Mirror native <button> keyboard activation for non-button elements:\n // Enter activates on keydown, Space on keyup (and must not scroll the page).\n const handleKeyDown = (e: React.KeyboardEvent<any>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === 'Enter') {\n e.preventDefault()\n e.currentTarget.click()\n } else if (e.key === ' ') {\n e.preventDefault()\n }\n }\n\n const handleKeyUp = (e: React.KeyboardEvent<any>) => {\n onKeyUp?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === ' ') {\n e.preventDefault()\n e.currentTarget.click()\n }\n }\n\n const elementProps = isNativeButton\n ? {\n type: type ?? 'button',\n // Not `disabled` while loading: that would drop keyboard focus from the\n // button just pressed. handleClick ignores presses until it's done.\n disabled: Boolean(disabled),\n 'aria-disabled': loading && !disabled ? true : undefined,\n role,\n tabIndex,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : isLink\n ? {\n role,\n tabIndex: resolvedDisabled ? -1 : tabIndex,\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : {\n role: role ?? 'button',\n tabIndex: resolvedDisabled ? -1 : (tabIndex ?? 0),\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }\n\n const sizeObj = SIZE_CLASSES[size] || SIZE_CLASSES.md\n\n const classes = useMemo(\n () =>\n buildClassName(\n BASE_BTN_CLASS,\n THEMED_BTN_CLASS[theme]?.[variant] || THEMED_BTN_CLASS.primary.default,\n iconOnly ? sizeObj.iconOnly : sizeObj.normal,\n // An outline (not a ring) so the offset gap stays transparent on any surface/mode.\n !noOutlineOnFocus &&\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid',\n rounded && 'rounded-full',\n fullWidth && 'w-full',\n // Secondary default is a flat grey fill; a shadow would bring back the outlined look.\n variant === 'default' && theme !== 'secondary' && 'shadow-xs hover:shadow-none',\n active && 'ring-2 ring-current',\n className,\n ),\n [theme, variant, sizeObj, iconOnly, noOutlineOnFocus, rounded, fullWidth, active, className],\n )\n\n // The spinner and loading text inherit the button's text colour.\n const loaderIcon = (\n <Loader\n data-testid=\"btn-loader-icon\"\n size={LOADER_SIZE[size] || 'xs'}\n className=\"text-current\"\n />\n )\n\n /**\n * SPECIAL CASE: iconOnly + loading → show spinner only\n */\n if (loading && iconOnly) {\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy=\"true\"\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loaderIcon}\n </Component>\n )\n }\n\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy={loading ? 'true' : undefined}\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loading ? (\n <span className=\"inline-flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n {loadingText ? (\n <TextContent className=\"text-current\">{loadingText}</TextContent>\n ) : (\n children\n )}\n </span>\n ) : (\n <>\n {leftIcon && <span className=\"shrink-0 inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"shrink-0 inline-flex items-center\">{rightIcon}</span>}\n </>\n )}\n </Component>\n )\n },\n) as ButtonComponent\n\nButton.displayName = 'Button'\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { Button } from '../Button/Button.js';
6
6
  import SvgChevronLeft from '../Icons/ChevronLeft.svg.js';
7
7
  import SvgX from '../Icons/X.svg.js';
8
8
  import { useResponsiveValue, useBreakpoint } from '../../hooks/use-breakpoint.js';
9
+ import { useCloseOnBack } from '../../hooks/use-close-on-back.js';
9
10
 
10
11
  const alignmentMap = {
11
12
  center: 'items-center justify-center h-full',
@@ -105,85 +106,6 @@ const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align
105
106
  : [panelAlignmentMap[align], panelSizeMap[size], panelClass])), "data-layout": fullscreen ? 'fullscreen' : undefined, children: [shouldShowDragHandle && (jsx("div", { className: "w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab", "data-testid": "drawer-drag-handle" })), fullscreen && (jsxs("div", { className: "sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800", children: [jsx(Button, { iconOnly: true, "aria-label": "Close", variant: "plain", theme: "secondary", onClick: onClose, className: "shrink-0", children: jsx(SvgX, { className: "size-5" }) }), title && (jsx(DialogTitle, { as: "h3", className: "min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white", children: title })), headerAction && jsx("div", { className: "ml-auto shrink-0", children: headerAction })] })), !fullscreen && showTitleSection && (jsxs("div", { className: buildClassName('space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0', titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10'), children: [jsxs("div", { className: "flex items-center justify-between gap-3 min-w-0", children: [jsxs("div", { className: "flex items-center gap-2 min-w-0 flex-1", children: [showBackButton && (jsx(Button, { iconOnly: true, "aria-label": "Back", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, children: jsx(SvgChevronLeft, { className: "size-4" }) })), title && (jsx(DialogTitle, { as: "h3", className: buildClassName('text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0', titleClass), children: title }))] }), showCloseButton && (jsx(Button, { iconOnly: true, "aria-label": "Close drawer", variant: "plain", theme: "secondary", size: "xs", onClick: onClose, className: "rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0", children: jsx(SvgX, { className: "size-4" }) }))] }), description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400 font-normal truncate', descriptionClass), children: description }))] })), jsxs("div", { className: buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass, fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]'), children: [fullscreen && description && (jsx("p", { className: buildClassName('text-sm text-gray-500 dark:text-gray-400', descriptionClass), children: description })), children] }), !fullscreen && footer && (jsx("div", { className: buildClassName('p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0', footerSticky && 'sticky bottom-0 z-10'), children: footer }))] }) }) })] }));
106
107
  };
107
108
  Drawer.displayName = 'Drawer';
108
- // history.back() lands later, so a drawer opening meanwhile (one replacing another,
109
- // or React re-running effects under StrictMode) would have its new entry removed
110
- // instead, and close at once. Removals are counted, and an opening drawer waits for them.
111
- let pendingBacks = 0;
112
- const afterBacks = [];
113
- function settleBack() {
114
- pendingBacks = Math.max(0, pendingBacks - 1);
115
- if (pendingBacks === 0)
116
- afterBacks.splice(0).forEach((run) => run());
117
- }
118
- function removeEntry() {
119
- pendingBacks += 1;
120
- let settled = false;
121
- const settle = () => {
122
- if (settled)
123
- return;
124
- settled = true;
125
- window.removeEventListener('popstate', settle);
126
- settleBack();
127
- };
128
- window.addEventListener('popstate', settle);
129
- // A back that never reports (nothing to go back to) mustn't hold others up.
130
- window.setTimeout(settle, 500);
131
- window.history.back();
132
- }
133
- /**
134
- * While `active`, the browser's back button (and Android's back gesture)
135
- * closes the drawer instead of leaving the page: opening adds a history entry
136
- * (keeping the current state, so routers see the same location), and back
137
- * removes it. Closed any other way, the entry is removed too, but only if it's
138
- * still the latest one, so a form that saves and then navigates isn't undone.
139
- */
140
- function useCloseOnBack(active, onClose) {
141
- const onCloseRef = React__default.useRef(onClose);
142
- React__default.useEffect(() => {
143
- onCloseRef.current = onClose;
144
- });
145
- const token = React__default.useId();
146
- React__default.useEffect(() => {
147
- if (!active || typeof window === 'undefined')
148
- return;
149
- const pushEntry = () => { var _a; return window.history.pushState({ ...((_a = window.history.state) !== null && _a !== void 0 ? _a : {}), drawer: token }, ''); };
150
- let entryPresent = false;
151
- let disposed = false;
152
- const handlePop = () => {
153
- var _a;
154
- if (((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
155
- return;
156
- entryPresent = false;
157
- onCloseRef.current();
158
- // onClose may step back within the drawer instead of closing it; if it's
159
- // still open afterwards, take back its entry so the next back works too.
160
- window.setTimeout(() => {
161
- if (disposed)
162
- return;
163
- pushEntry();
164
- entryPresent = true;
165
- }, 0);
166
- };
167
- const start = () => {
168
- if (disposed)
169
- return;
170
- pushEntry();
171
- entryPresent = true;
172
- window.addEventListener('popstate', handlePop);
173
- };
174
- if (pendingBacks > 0)
175
- afterBacks.push(start);
176
- else
177
- start();
178
- return () => {
179
- var _a;
180
- disposed = true;
181
- window.removeEventListener('popstate', handlePop);
182
- if (entryPresent && ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
183
- removeEntry();
184
- };
185
- }, [active, token]);
186
- }
187
109
 
188
110
  export { Drawer };
189
111
  //# sourceMappingURL=Drawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport { useBreakpoint, useResponsiveValue } from '../../hooks/use-breakpoint'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n // Bottom sheets clear the home indicator on notched phones (0 elsewhere). Never\n // taller than the container: with the keyboard up it's shorter than 88dvh, and a\n // bottom-anchored panel past its top is off screen and can't be scrolled to.\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[min(88dvh,100%)] pb-[env(safe-area-inset-bottom,0px)]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\n// How much shorter than the window the visual viewport must be before it's\n// taken to be the on-screen keyboard rather than the URL bar (≈ 56px).\nconst KEYBOARD_THRESHOLD = 150\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align: alignProp = 'end',\n size: sizeProp = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n phoneLayout = 'default',\n headerAction,\n}) => {\n const align = useResponsiveValue(alignProp)\n const size = useResponsiveValue(sizeProp)\n const breakpoint = useBreakpoint()\n const fullscreen = phoneLayout === 'fullscreen' && breakpoint === 'compact'\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = !fullscreen && (dragHandle ?? align === 'bottom')\n useCloseOnBack(fullscreen && isOpen, onClose)\n // The visible area while the on-screen keyboard is open; null otherwise.\n const [keyboardViewport, setKeyboardViewport] = React.useState<{\n top: number\n height: number\n } | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setKeyboardViewport(null)\n return\n }\n\n // Follow the visual viewport only while the on-screen keyboard takes space\n // (it's then much shorter than the window), so the drawer and its footer\n // stay above the keyboard. Otherwise it's pinned to the edges: tracking every resize and\n // scroll in state re-rendered the drawer on each frame as the browser's\n // URL bar moved, and its sticky header and footer jumped while scrolling.\n let frame = 0\n const measure = () => {\n frame = 0\n const vv = window.visualViewport\n if (!vv) return\n const keyboardOpen = window.innerHeight - vv.height > KEYBOARD_THRESHOLD\n const top = Math.round(vv.offsetTop)\n const height = Math.round(vv.height)\n // The browser scrolls the visible area to the focused field, so the\n // drawer follows its offset as well as its height. An unchanged value\n // doesn't re-render.\n setKeyboardViewport((current) =>\n !keyboardOpen\n ? null\n : current && current.top === top && current.height === height\n ? current\n : { top, height },\n )\n }\n const updateHeight = () => {\n if (!frame) frame = window.requestAnimationFrame(measure)\n }\n\n measure()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n if (frame) window.cancelAnimationFrame(frame)\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n {/* Pinned to all four edges rather than given a height: mobile browsers\n move fixed edges with the URL bar on every frame, while 100dvh only\n updates once its animation ends (the drawer briefly came up short).\n With the keyboard open it takes the visible area's offset and height. */}\n <div\n className=\"fixed inset-0\"\n style={\n keyboardViewport\n ? {\n top: `${keyboardViewport.top}px`,\n height: `${keyboardViewport.height}px`,\n bottom: 'auto',\n }\n : undefined\n }\n data-testid=\"drawer-viewport\"\n >\n <div className={buildClassName('flex', fullscreen ? 'h-full' : alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n ...(fullscreen\n ? ['h-full data-[closed]:translate-y-4']\n : [panelAlignmentMap[align], panelSizeMap[size], panelClass]),\n )}\n data-layout={fullscreen ? 'fullscreen' : undefined}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Phone full-screen bar: the only fixed part, so the fields keep the room. */}\n {fullscreen && (\n <div className=\"sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800\">\n <Button\n iconOnly\n aria-label=\"Close\"\n variant=\"plain\"\n theme=\"secondary\"\n onClick={onClose}\n className=\"shrink-0\"\n >\n <XIcon className=\"size-5\" />\n </Button>\n {title && (\n <DialogTitle\n as=\"h3\"\n className=\"min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white\"\n >\n {title}\n </DialogTitle>\n )}\n {headerAction && <div className=\"ml-auto shrink-0\">{headerAction}</div>}\n </div>\n )}\n\n {/* Header Section */}\n {!fullscreen && showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div\n className={buildClassName(\n 'flex-1 p-4 md:p-6 space-y-4 min-w-0',\n contentClass,\n fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]',\n )}\n >\n {fullscreen && description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n {children}\n </div>\n\n {/* Footer Section (the phone full-screen bar carries the action instead) */}\n {!fullscreen && footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n\n// history.back() lands later, so a drawer opening meanwhile (one replacing another,\n// or React re-running effects under StrictMode) would have its new entry removed\n// instead, and close at once. Removals are counted, and an opening drawer waits for them.\nlet pendingBacks = 0\nconst afterBacks: Array<() => void> = []\n\nfunction settleBack() {\n pendingBacks = Math.max(0, pendingBacks - 1)\n if (pendingBacks === 0) afterBacks.splice(0).forEach((run) => run())\n}\n\nfunction removeEntry() {\n pendingBacks += 1\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n window.removeEventListener('popstate', settle)\n settleBack()\n }\n window.addEventListener('popstate', settle)\n // A back that never reports (nothing to go back to) mustn't hold others up.\n window.setTimeout(settle, 500)\n window.history.back()\n}\n\n/**\n * While `active`, the browser's back button (and Android's back gesture)\n * closes the drawer instead of leaving the page: opening adds a history entry\n * (keeping the current state, so routers see the same location), and back\n * removes it. Closed any other way, the entry is removed too, but only if it's\n * still the latest one, so a form that saves and then navigates isn't undone.\n */\nfunction useCloseOnBack(active: boolean, onClose: () => void) {\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n })\n const token = React.useId()\n\n React.useEffect(() => {\n if (!active || typeof window === 'undefined') return\n const pushEntry = () =>\n window.history.pushState({ ...(window.history.state ?? {}), drawer: token }, '')\n let entryPresent = false\n let disposed = false\n const handlePop = () => {\n if (window.history.state?.drawer === token) return\n entryPresent = false\n onCloseRef.current()\n // onClose may step back within the drawer instead of closing it; if it's\n // still open afterwards, take back its entry so the next back works too.\n window.setTimeout(() => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n }, 0)\n }\n const start = () => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n window.addEventListener('popstate', handlePop)\n }\n if (pendingBacks > 0) afterBacks.push(start)\n else start()\n return () => {\n disposed = true\n window.removeEventListener('popstate', handlePop)\n if (entryPresent && window.history.state?.drawer === token) removeEntry()\n }\n }, [active, token])\n}\n"],"names":["React","_jsxs","_jsx","XIcon","ChevronLeftIcon"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport { useBreakpoint, useResponsiveValue } from '../../hooks/use-breakpoint'\nimport { useCloseOnBack } from '../../hooks/use-close-on-back'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n // Bottom sheets clear the home indicator on notched phones (0 elsewhere). Never\n // taller than the container: with the keyboard up it's shorter than 88dvh, and a\n // bottom-anchored panel past its top is off screen and can't be scrolled to.\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[min(88dvh,100%)] pb-[env(safe-area-inset-bottom,0px)]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\n// How much shorter than the window the visual viewport must be before it's\n// taken to be the on-screen keyboard rather than the URL bar (≈ 56px).\nconst KEYBOARD_THRESHOLD = 150\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align: alignProp = 'end',\n size: sizeProp = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n phoneLayout = 'default',\n headerAction,\n}) => {\n const align = useResponsiveValue(alignProp)\n const size = useResponsiveValue(sizeProp)\n const breakpoint = useBreakpoint()\n const fullscreen = phoneLayout === 'fullscreen' && breakpoint === 'compact'\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = !fullscreen && (dragHandle ?? align === 'bottom')\n useCloseOnBack(fullscreen && isOpen, onClose)\n // The visible area while the on-screen keyboard is open; null otherwise.\n const [keyboardViewport, setKeyboardViewport] = React.useState<{\n top: number\n height: number\n } | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setKeyboardViewport(null)\n return\n }\n\n // Follow the visual viewport only while the on-screen keyboard takes space\n // (it's then much shorter than the window), so the drawer and its footer\n // stay above the keyboard. Otherwise it's pinned to the edges: tracking every resize and\n // scroll in state re-rendered the drawer on each frame as the browser's\n // URL bar moved, and its sticky header and footer jumped while scrolling.\n let frame = 0\n const measure = () => {\n frame = 0\n const vv = window.visualViewport\n if (!vv) return\n const keyboardOpen = window.innerHeight - vv.height > KEYBOARD_THRESHOLD\n const top = Math.round(vv.offsetTop)\n const height = Math.round(vv.height)\n // The browser scrolls the visible area to the focused field, so the\n // drawer follows its offset as well as its height. An unchanged value\n // doesn't re-render.\n setKeyboardViewport((current) =>\n !keyboardOpen\n ? null\n : current && current.top === top && current.height === height\n ? current\n : { top, height },\n )\n }\n const updateHeight = () => {\n if (!frame) frame = window.requestAnimationFrame(measure)\n }\n\n measure()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n if (frame) window.cancelAnimationFrame(frame)\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n {/* Pinned to all four edges rather than given a height: mobile browsers\n move fixed edges with the URL bar on every frame, while 100dvh only\n updates once its animation ends (the drawer briefly came up short).\n With the keyboard open it takes the visible area's offset and height. */}\n <div\n className=\"fixed inset-0\"\n style={\n keyboardViewport\n ? {\n top: `${keyboardViewport.top}px`,\n height: `${keyboardViewport.height}px`,\n bottom: 'auto',\n }\n : undefined\n }\n data-testid=\"drawer-viewport\"\n >\n <div className={buildClassName('flex', fullscreen ? 'h-full' : alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n ...(fullscreen\n ? ['h-full data-[closed]:translate-y-4']\n : [panelAlignmentMap[align], panelSizeMap[size], panelClass]),\n )}\n data-layout={fullscreen ? 'fullscreen' : undefined}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Phone full-screen bar: the only fixed part, so the fields keep the room. */}\n {fullscreen && (\n <div className=\"sticky top-0 z-10 flex h-14 shrink-0 items-center gap-1 border-b border-[var(--ui-border)] bg-white pl-1 pr-3 pt-[env(safe-area-inset-top,0px)] box-content dark:bg-gray-800\">\n <Button\n iconOnly\n aria-label=\"Close\"\n variant=\"plain\"\n theme=\"secondary\"\n onClick={onClose}\n className=\"shrink-0\"\n >\n <XIcon className=\"size-5\" />\n </Button>\n {title && (\n <DialogTitle\n as=\"h3\"\n className=\"min-w-0 flex-1 truncate text-base font-semibold text-gray-900 dark:text-white\"\n >\n {title}\n </DialogTitle>\n )}\n {headerAction && <div className=\"ml-auto shrink-0\">{headerAction}</div>}\n </div>\n )}\n\n {/* Header Section */}\n {!fullscreen && showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div\n className={buildClassName(\n 'flex-1 p-4 md:p-6 space-y-4 min-w-0',\n contentClass,\n fullscreen && 'pb-[calc(1rem+env(safe-area-inset-bottom,0px))]',\n )}\n >\n {fullscreen && description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n {children}\n </div>\n\n {/* Footer Section (the phone full-screen bar carries the action instead) */}\n {!fullscreen && footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n"],"names":["React","_jsxs","_jsx","XIcon","ChevronLeftIcon"],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import React__default from 'react';
2
+
3
+ // history.back() lands later, so a drawer opening meanwhile (one replacing another,
4
+ // or React re-running effects under StrictMode) would have its new entry removed
5
+ // instead, and close at once. Removals are counted, and an opening drawer waits for them.
6
+ let pendingBacks = 0;
7
+ const afterBacks = [];
8
+ function settleBack() {
9
+ pendingBacks = Math.max(0, pendingBacks - 1);
10
+ if (pendingBacks === 0)
11
+ afterBacks.splice(0).forEach((run) => run());
12
+ }
13
+ function removeEntry() {
14
+ pendingBacks += 1;
15
+ let settled = false;
16
+ const settle = () => {
17
+ if (settled)
18
+ return;
19
+ settled = true;
20
+ window.removeEventListener('popstate', settle);
21
+ settleBack();
22
+ };
23
+ window.addEventListener('popstate', settle);
24
+ // A back that never reports (nothing to go back to) mustn't hold others up.
25
+ window.setTimeout(settle, 500);
26
+ window.history.back();
27
+ }
28
+ /**
29
+ * While `active`, the browser's back button (and Android's back gesture)
30
+ * closes the drawer instead of leaving the page: opening adds a history entry
31
+ * (keeping the current state, so routers see the same location), and back
32
+ * removes it. Closed any other way, the entry is removed too, but only if it's
33
+ * still the latest one, so a form that saves and then navigates isn't undone.
34
+ */
35
+ function useCloseOnBack(active, onClose) {
36
+ const onCloseRef = React__default.useRef(onClose);
37
+ React__default.useEffect(() => {
38
+ onCloseRef.current = onClose;
39
+ });
40
+ const token = React__default.useId();
41
+ React__default.useEffect(() => {
42
+ if (!active || typeof window === 'undefined')
43
+ return;
44
+ const pushEntry = () => { var _a; return window.history.pushState({ ...((_a = window.history.state) !== null && _a !== void 0 ? _a : {}), drawer: token }, ''); };
45
+ let entryPresent = false;
46
+ let disposed = false;
47
+ const handlePop = () => {
48
+ var _a;
49
+ if (((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
50
+ return;
51
+ entryPresent = false;
52
+ onCloseRef.current();
53
+ // onClose may step back within the drawer instead of closing it; if it's
54
+ // still open afterwards, take back its entry so the next back works too.
55
+ window.setTimeout(() => {
56
+ if (disposed)
57
+ return;
58
+ pushEntry();
59
+ entryPresent = true;
60
+ }, 0);
61
+ };
62
+ const start = () => {
63
+ if (disposed)
64
+ return;
65
+ pushEntry();
66
+ entryPresent = true;
67
+ window.addEventListener('popstate', handlePop);
68
+ };
69
+ if (pendingBacks > 0)
70
+ afterBacks.push(start);
71
+ else
72
+ start();
73
+ return () => {
74
+ var _a;
75
+ disposed = true;
76
+ window.removeEventListener('popstate', handlePop);
77
+ if (entryPresent && ((_a = window.history.state) === null || _a === void 0 ? void 0 : _a.drawer) === token)
78
+ removeEntry();
79
+ };
80
+ }, [active, token]);
81
+ }
82
+
83
+ export { useCloseOnBack };
84
+ //# sourceMappingURL=use-close-on-back.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-close-on-back.js","sources":["../../../../src/hooks/use-close-on-back.ts"],"sourcesContent":["import React from 'react'\n\n// history.back() lands later, so a drawer opening meanwhile (one replacing another,\n// or React re-running effects under StrictMode) would have its new entry removed\n// instead, and close at once. Removals are counted, and an opening drawer waits for them.\nlet pendingBacks = 0\nconst afterBacks: Array<() => void> = []\n\nfunction settleBack() {\n pendingBacks = Math.max(0, pendingBacks - 1)\n if (pendingBacks === 0) afterBacks.splice(0).forEach((run) => run())\n}\n\nfunction removeEntry() {\n pendingBacks += 1\n let settled = false\n const settle = () => {\n if (settled) return\n settled = true\n window.removeEventListener('popstate', settle)\n settleBack()\n }\n window.addEventListener('popstate', settle)\n // A back that never reports (nothing to go back to) mustn't hold others up.\n window.setTimeout(settle, 500)\n window.history.back()\n}\n\n/**\n * While `active`, the browser's back button (and Android's back gesture)\n * closes the drawer instead of leaving the page: opening adds a history entry\n * (keeping the current state, so routers see the same location), and back\n * removes it. Closed any other way, the entry is removed too, but only if it's\n * still the latest one, so a form that saves and then navigates isn't undone.\n */\nexport function useCloseOnBack(active: boolean, onClose: () => void) {\n const onCloseRef = React.useRef(onClose)\n React.useEffect(() => {\n onCloseRef.current = onClose\n })\n const token = React.useId()\n\n React.useEffect(() => {\n if (!active || typeof window === 'undefined') return\n const pushEntry = () =>\n window.history.pushState({ ...(window.history.state ?? {}), drawer: token }, '')\n let entryPresent = false\n let disposed = false\n const handlePop = () => {\n if (window.history.state?.drawer === token) return\n entryPresent = false\n onCloseRef.current()\n // onClose may step back within the drawer instead of closing it; if it's\n // still open afterwards, take back its entry so the next back works too.\n window.setTimeout(() => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n }, 0)\n }\n const start = () => {\n if (disposed) return\n pushEntry()\n entryPresent = true\n window.addEventListener('popstate', handlePop)\n }\n if (pendingBacks > 0) afterBacks.push(start)\n else start()\n return () => {\n disposed = true\n window.removeEventListener('popstate', handlePop)\n if (entryPresent && window.history.state?.drawer === token) removeEntry()\n }\n }, [active, token])\n}\n"],"names":["React"],"mappings":"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"}
package/dist/es/index.js CHANGED
@@ -57,6 +57,7 @@ export { ToastProvider, useToast } from './components/Toast/ToastProvider.js';
57
57
  export { Toast } from './components/Toast/Toast.js';
58
58
  export { VirtualizedDataTable } from './components/VirtualizedDataTable/VirtualizedDataTable.js';
59
59
  export { BREAKPOINT_QUERIES, useBreakpoint, useMediaQuery, useResponsiveValue } from './hooks/use-breakpoint.js';
60
+ export { useCloseOnBack } from './hooks/use-close-on-back.js';
60
61
  export { useDebounce, useDebounceFn } from './hooks/use-debounce.js';
61
62
  export { useIsMobile } from './hooks/use-is-mobile.js';
62
63
  export { useIsTablet } from './hooks/use-is-tablet.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}