@kanso-labs/kanso-ui 0.34.0 → 0.34.2
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/collection/text.js +17 -0
- package/dist/collection/text.js.map +1 -0
- package/dist/components/avatar/index.js +49 -34
- package/dist/components/avatar/index.js.map +1 -1
- package/dist/components/chip-group/index.js +1 -3
- package/dist/components/chip-group/index.js.map +1 -1
- package/dist/components/color-picker/index.d.ts +2 -2
- package/dist/components/color-picker/index.js.map +1 -1
- package/dist/components/combo-box/index.js +112 -77
- package/dist/components/combo-box/index.js.map +1 -1
- package/dist/components/disclosure/index.js +35 -29
- package/dist/components/disclosure/index.js.map +1 -1
- package/dist/components/link/index.js.map +1 -1
- package/dist/components/list/index.d.ts +1 -1
- package/dist/components/list/index.js +70 -50
- package/dist/components/list/index.js.map +1 -1
- package/dist/components/list-box/index.d.ts +1 -1
- package/dist/components/list-box/index.js +72 -88
- package/dist/components/list-box/index.js.map +1 -1
- package/dist/components/menu/index.d.ts +4 -3
- package/dist/components/menu/index.js +57 -69
- package/dist/components/menu/index.js.map +1 -1
- package/dist/components/meter/index.d.ts +3 -2
- package/dist/components/meter/index.js.map +1 -1
- package/dist/components/navigation-tree/index.d.ts +1 -1
- package/dist/components/navigation-tree/index.js +62 -76
- package/dist/components/navigation-tree/index.js.map +1 -1
- package/dist/components/product-icon/index.js +49 -34
- package/dist/components/product-icon/index.js.map +1 -1
- package/dist/components/token-field/index.js +4 -2
- package/dist/components/token-field/index.js.map +1 -1
- package/dist/components/tree/index.d.ts +1 -1
- package/dist/components/tree/index.js +74 -52
- package/dist/components/tree/index.js.map +1 -1
- package/dist/hooks/useImageLoadingStatus.js +14 -7
- package/dist/hooks/useImageLoadingStatus.js.map +1 -1
- package/dist/hooks/useRipple.js +209 -216
- package/dist/hooks/useRipple.js.map +1 -1
- package/dist/styles/overlay.js +1 -0
- package/dist/styles/overlay.js.map +1 -1
- package/dist/styles.css +4 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRipple.js","names":["MouseEvent","MouseEventHandler","PointerEvent","PointerEventHandler","ReactNode","stylex","useCallback","useMemo","useRef","useState","rippleStyles","motionDurationMs","motionEasing","spacingPx","PADDING","sm","INITIAL_ORIGIN_SCALE","SOFT_EDGE_MINIMUM_SIZE","SOFT_EDGE_CONTAINER_RATIO","surfaceProps","props","surface","RippleState","Holding","Inactive","TouchDelay","WaitingForClick","const","RippleEventHandlers","Element","onClick","HostElement","onContextMenu","onPointerCancel","onPointerDown","onPointerLeave","onPointerUp","isTouch","event","pointerType","prefersReducedMotion","window","matchMedia","matches","useRipple","t0","t1","$","_c","enabled","undefined","t2","externalHandlers","pressed","setPressed","rippleRef","state","growAnimation","rippleStartEvent","initialSize","rippleScale","t3","Symbol","for","isPrimary","startEvent","current","pointerId","buttons","shouldReactToEvent","t4","rect","height","width","maxDimension","Math","max","softEdgeSize","size","floor","hypotenuse","hypot","maxRadius","determineRippleSize","t5","rect_0","positionEvent","height_0","left","top","width_0","size_0","endPoint","x","y","origin","clientX","clientY","startPoint","getTranslationCoordinates","t6","target","positionEvent_0","ripple","cancel","rect_1","getBoundingClientRect","size_1","endPoint_0","startPoint_0","style","animate","transform","duration","long1","easing","standard","fill","startPressAnimation","t7","animation","elapsed","currentTime","Infinity","medium1","Promise","resolve","setTimeout","endPressAnimation","t8","getState","t9","event_0","target_0","currentTarget","_temp","handlePointerDownAsync","t10","event_1","handlePointerDown","t11","event_2","handlePointerUp","t12","event_3","handlePointerLeave","t13","event_4","handlePointerCancel","t14","event_5","handleClick","t15","handleContextMenu","onClickProp","onContextMenuProp","onPointerCancelProp","onPointerDownProp","onPointerLeaveProp","onPointerUpProp","t16","event_6","t17","event_7","t18","event_8","t19","event_9","t20","event_10","t21","event_11","t22","handlers","t23","press","t24","t25","enabledResult","t26","disabledResult","resolve_0","short2"],"sources":["../../src/hooks/useRipple.tsx"],"sourcesContent":["import type { MouseEvent, MouseEventHandler, PointerEvent, PointerEventHandler, ReactNode } from 'react';\nimport * as stylex from '@stylexjs/stylex';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { rippleStyles } from '../styles/ripple';\nimport { motionDurationMs, motionEasing, spacingPx } from '../tokens/values';\n\n// Every timing this file drives is a motion token, spent at the point of use\n// below. They come from tokens/values rather than the StyleX theme because\n// element.animate() and setTimeout both reject a token's var() form, and the\n// same is true of the one geometry token: `PADDING` is added to a radius, and\n// a var() would concatenate rather than add. See src/styles/ripple.ts for the\n// opacity half of the mechanism, whose three timings are deliberately not\n// tokens.\n\n/** How far the ripple grows past the host's corners. `spacing.sm`. */\nconst PADDING = spacingPx.sm;\n\n// The rest are ratios and a pixel floor that no token group covers — spacing\n// is layout rhythm, and nothing in the set holds bare geometric ratios.\nconst INITIAL_ORIGIN_SCALE = 0.2;\nconst SOFT_EDGE_MINIMUM_SIZE = 75;\nconst SOFT_EDGE_CONTAINER_RATIO = 0.35;\n\n// Static input, so this is computed once for every consumer of the module\n// rather than once per component instance.\nconst surfaceProps = stylex.props(rippleStyles.surface);\n\n/**\n * On touch: `Inactive -> TouchDelay -> WaitingForClick -> Inactive`, or\n * `Inactive -> TouchDelay -> Holding -> WaitingForClick -> Inactive` for a\n * held press.\n *\n * On mouse or pen: `Inactive -> WaitingForClick -> Inactive`.\n */\nconst RippleState = {\n /** A touch has been confirmed as a press (held past the touch delay). */\n Holding: 2,\n /** No press in progress. Touch down moves to TouchDelay; mouse/pen down moves to WaitingForClick. */\n Inactive: 0,\n /** Touch down received; waiting to see if it's a tap or a scroll/swipe. */\n TouchDelay: 1,\n /** The press has finished growing; waiting for the click that ends it. */\n WaitingForClick: 3\n} as const;\ninterface RippleEventHandlers<HostElement extends Element> {\n onClick?: MouseEventHandler<HostElement>;\n onContextMenu?: MouseEventHandler<HostElement>;\n onPointerCancel?: PointerEventHandler<HostElement>;\n onPointerDown?: PointerEventHandler<HostElement>;\n onPointerLeave?: PointerEventHandler<HostElement>;\n onPointerUp?: PointerEventHandler<HostElement>;\n}\ntype RippleState = (typeof RippleState)[keyof typeof RippleState];\nfunction isTouch(event: PointerEvent) {\n return event.pointerType === 'touch';\n}\n\n/**\n * Whether the reader has asked the OS for less motion.\n *\n * Growth is a Web Animations call, which makes it the one animation in the\n * library no `@media (prefers-reduced-motion: reduce)` branch can reach — see\n * src/styles/ripple.ts for the opacity half, which is CSS and carries one.\n *\n * Read at the press rather than once at mount, so a reader who changes the\n * setting is answered by their next press rather than by their next reload.\n * The press already reads layout through `getBoundingClientRect`, which costs\n * more than this does.\n */\nfunction prefersReducedMotion() {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Renders a press ripple that grows from the pointer's position, or from\n * the element's center for a keyboard or other non-pointer activation.\n *\n * Growth runs via the Web Animations API on a single reused element (no\n * per-click DOM nodes to clean up), over a fixed duration independent of how\n * long the element is held — a real press-and-hold keeps the ripple\n * growing until release, while a quick tap is still held visible for a\n * minimum duration so it plays a complete animation rather than a flicker.\n *\n * Merges its own handlers with `externalHandlers` (e.g. a component's own\n * consumer-supplied props — ripple's own run first, then the external\n * ones) and returns `handlers` to spread onto the interactive element and\n * `surface`, the node to render as a child. The host element must\n * establish a positioning context (`position: relative` or similar) so\n * `surface`, which fills it via `inset: 0`, clips to its bounds and\n * inherits its shape.\n *\n * Pass `enabled: false` to opt out — no ripple listeners are attached and\n * no surface is rendered, leaving `externalHandlers` and a component's own\n * hover/press state layer (if any) untouched.\n *\n * `handlers` and `surface` are hand-memoized (not left to build-tool\n * optimization) so a consumer rendering many instances — a list of icon\n * buttons, say — can memoize around them too, and so stability doesn't\n * depend on any particular compiler being configured.\n */\nfunction useRipple<HostElement extends Element = Element>(enabled = true, externalHandlers: RippleEventHandlers<HostElement> = {}): {\n handlers: RippleEventHandlers<HostElement>;\n surface: ReactNode;\n} {\n const [pressed, setPressed] = useState(false);\n const rippleRef = useRef<HTMLSpanElement>(null);\n const state = useRef<RippleState>(RippleState.Inactive);\n const growAnimation = useRef<Animation | undefined>(undefined);\n const rippleStartEvent = useRef<PointerEvent<HostElement> | undefined>(undefined);\n const initialSize = useRef(0);\n const rippleScale = useRef('1');\n const shouldReactToEvent = useCallback((event: PointerEvent<HostElement>) => {\n if (!event.isPrimary) {\n return false;\n }\n const startEvent = rippleStartEvent.current;\n if (startEvent && startEvent.pointerId !== event.pointerId) {\n return false;\n }\n return isTouch(event) || event.buttons === 1;\n }, []);\n const determineRippleSize = useCallback((rect: DOMRect) => {\n const {\n height,\n width\n } = rect;\n const maxDimension = Math.max(height, width);\n const softEdgeSize = Math.max(SOFT_EDGE_CONTAINER_RATIO * maxDimension, SOFT_EDGE_MINIMUM_SIZE);\n const size = Math.floor(maxDimension * INITIAL_ORIGIN_SCALE);\n const hypotenuse = Math.hypot(width, height);\n const maxRadius = hypotenuse + PADDING;\n initialSize.current = size;\n rippleScale.current = `${(maxRadius + softEdgeSize) / size}`;\n return `${size}px`;\n }, []);\n const getTranslationCoordinates = useCallback((rect: DOMRect, positionEvent?: PointerEvent<HostElement>) => {\n const {\n height,\n left,\n top,\n width\n } = rect;\n const size = initialSize.current;\n const endPoint = {\n x: (width - size) / 2,\n y: (height - size) / 2\n };\n const origin = positionEvent ? {\n x: positionEvent.clientX - left,\n y: positionEvent.clientY - top\n } : {\n x: width / 2,\n y: height / 2\n };\n const startPoint = {\n x: origin.x - size / 2,\n y: origin.y - size / 2\n };\n return {\n endPoint,\n startPoint\n };\n }, []);\n const startPressAnimation = useCallback((target: HostElement, positionEvent?: PointerEvent<HostElement>) => {\n const ripple = rippleRef.current;\n if (!ripple) {\n return;\n }\n setPressed(true);\n growAnimation.current?.cancel();\n\n // Read once and share: the two helpers below both only need the\n // target's rect, and a second `getBoundingClientRect()` call back to\n // back with the first would be a redundant layout read.\n const rect = target.getBoundingClientRect();\n const size = determineRippleSize(rect);\n const {\n endPoint,\n startPoint\n } = getTranslationCoordinates(rect, positionEvent);\n ripple.style.width = size;\n ripple.style.height = size;\n growAnimation.current = ripple.animate({\n transform: [`translate(${startPoint.x}px, ${startPoint.y}px) scale(1)`, `translate(${endPoint.x}px, ${endPoint.y}px) scale(${rippleScale.current})`]\n }, {\n // Growth runs over a fixed duration regardless of how long the\n // press is held, so the token is spent here rather than named as a\n // constant — element.animate() is one of the two places a StyleX\n // token could not have gone.\n //\n // Zeroed rather than skipped under reduced motion, which lands the\n // disc at its full size with the growth never drawn. Skipping the\n // call outright would leave `growAnimation` unset, and the release\n // below reads its `currentTime` to decide whether the press has\n // been visible long enough — so the press would still be shown, and\n // would stop being held for its minimum.\n duration: prefersReducedMotion() ? 0 : motionDurationMs.long1,\n easing: motionEasing.standard,\n fill: 'forwards'\n });\n }, [determineRippleSize, getTranslationCoordinates]);\n const endPressAnimation = useCallback(async () => {\n rippleStartEvent.current = undefined;\n state.current = RippleState.Inactive;\n const animation = growAnimation.current;\n const elapsed = typeof animation?.currentTime === 'number' ? animation.currentTime : Infinity;\n\n // The floor on how briefly a ripple may be visible, so a quick tap reads\n // as a deliberate ripple rather than a flicker.\n if (elapsed >= motionDurationMs.medium1) {\n setPressed(false);\n return;\n }\n await new Promise(resolve => {\n setTimeout(resolve, motionDurationMs.medium1 - elapsed);\n });\n if (growAnimation.current !== animation) {\n // A newer press started; let it own the pressed state instead.\n return;\n }\n setPressed(false);\n }, []);\n\n // Reads through a function so a stale narrowing of `state.current` from\n // before the `await` below isn't (incorrectly) carried across it — the\n // ref can change via a different handler while this one is suspended.\n const getState = useCallback(() => state.current, []);\n const handlePointerDownAsync = useCallback(async (event: PointerEvent<HostElement>) => {\n if (!shouldReactToEvent(event)) {\n return;\n }\n rippleStartEvent.current = event;\n const target = event.currentTarget;\n if (!isTouch(event)) {\n state.current = RippleState.WaitingForClick;\n startPressAnimation(target, event);\n return;\n }\n\n // Delay so a scroll/swipe starting on the element doesn't flash a\n // ripple — only a held (or quickly released) touch counts as a press.\n state.current = RippleState.TouchDelay;\n await new Promise(resolve => {\n setTimeout(resolve, motionDurationMs.short2);\n });\n if (getState() !== RippleState.TouchDelay) {\n return;\n }\n state.current = RippleState.Holding;\n startPressAnimation(target, event);\n }, [getState, shouldReactToEvent, startPressAnimation]);\n const handlePointerDown = useCallback((event: PointerEvent<HostElement>) => {\n void handlePointerDownAsync(event);\n }, [handlePointerDownAsync]);\n const handlePointerUp = useCallback((event: PointerEvent<HostElement>) => {\n if (!shouldReactToEvent(event)) {\n return;\n }\n if (state.current === RippleState.Holding) {\n state.current = RippleState.WaitingForClick;\n return;\n }\n if (state.current === RippleState.TouchDelay) {\n // Released before the delay elapsed: treat as a completed tap.\n state.current = RippleState.WaitingForClick;\n startPressAnimation(event.currentTarget, rippleStartEvent.current);\n }\n }, [shouldReactToEvent, startPressAnimation]);\n const handlePointerLeave = useCallback((event: PointerEvent<HostElement>) => {\n if (isTouch(event) || !shouldReactToEvent(event)) {\n return;\n }\n if (state.current !== RippleState.Inactive) {\n void endPressAnimation();\n }\n }, [endPressAnimation, shouldReactToEvent]);\n const handlePointerCancel = useCallback((event: PointerEvent<HostElement>) => {\n if (!shouldReactToEvent(event)) {\n return;\n }\n void endPressAnimation();\n }, [endPressAnimation, shouldReactToEvent]);\n const handleClick = useCallback((event: MouseEvent<HostElement>) => {\n if (state.current === RippleState.WaitingForClick) {\n void endPressAnimation();\n return;\n }\n if (state.current === RippleState.Inactive) {\n // No pointerdown preceded this click — keyboard activation, a\n // programmatic `.click()`, or assistive-tech-synthesized activation.\n // Play a complete, centered press immediately.\n startPressAnimation(event.currentTarget);\n void endPressAnimation();\n }\n }, [endPressAnimation, startPressAnimation]);\n const handleContextMenu = useCallback(() => {\n void endPressAnimation();\n }, [endPressAnimation]);\n const {\n onClick: onClickProp,\n onContextMenu: onContextMenuProp,\n onPointerCancel: onPointerCancelProp,\n onPointerDown: onPointerDownProp,\n onPointerLeave: onPointerLeaveProp,\n onPointerUp: onPointerUpProp\n } = externalHandlers;\n const onClick = useCallback((event: MouseEvent<HostElement>) => {\n handleClick(event);\n onClickProp?.(event);\n }, [handleClick, onClickProp]);\n const onContextMenu = useCallback((event: MouseEvent<HostElement>) => {\n handleContextMenu();\n onContextMenuProp?.(event);\n }, [handleContextMenu, onContextMenuProp]);\n const onPointerCancel = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerCancel(event);\n onPointerCancelProp?.(event);\n }, [handlePointerCancel, onPointerCancelProp]);\n const onPointerDown = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerDown(event);\n onPointerDownProp?.(event);\n }, [handlePointerDown, onPointerDownProp]);\n const onPointerLeave = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerLeave(event);\n onPointerLeaveProp?.(event);\n }, [handlePointerLeave, onPointerLeaveProp]);\n const onPointerUp = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerUp(event);\n onPointerUpProp?.(event);\n }, [handlePointerUp, onPointerUpProp]);\n const handlers = useMemo(() => ({\n onClick,\n onContextMenu,\n onPointerCancel,\n onPointerDown,\n onPointerLeave,\n onPointerUp\n }), [onClick, onContextMenu, onPointerCancel, onPointerDown, onPointerLeave, onPointerUp]);\n const surface = useMemo(() => <span aria-hidden=\"true\" {...surfaceProps}>\n <span ref={rippleRef} {...stylex.props(rippleStyles.press, pressed && rippleStyles.pressed)} />\n </span>, [pressed]);\n\n // Two separate memos rather than one branching on `enabled`, so that\n // whichever branch is actually active stays keyed only on its own\n // inputs — the enabled result doesn't get a new identity every time\n // `externalHandlers` does (a component typically passes a fresh object\n // literal each render), and vice versa.\n const enabledResult = useMemo(() => ({\n handlers,\n surface\n }), [handlers, surface]);\n const disabledResult = useMemo(() => ({\n handlers: externalHandlers,\n surface: null\n }), [externalHandlers]);\n return enabled ? enabledResult : disabledResult;\n}\nexport { useRipple };"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useRipple.js","names":["MouseEvent","MouseEventHandler","PointerEvent","PointerEventHandler","ReactNode","stylex","useCallback","useMemo","useRef","useState","rippleStyles","motionDurationMs","motionEasing","spacingPx","PADDING","sm","INITIAL_ORIGIN_SCALE","SOFT_EDGE_MINIMUM_SIZE","SOFT_EDGE_CONTAINER_RATIO","surfaceProps","props","surface","RippleState","Holding","Inactive","TouchDelay","WaitingForClick","const","ReleaseHandlers","Element","Omit","RippleEventHandlers","HostElement","onClick","onContextMenu","onPointerCancel","onPointerDown","onPointerLeave","onPointerUp","isTouch","event","pointerType","prefersReducedMotion","window","matchMedia","matches","useRipple","enabled","externalHandlers","endsOnRelease","handlers","t0","t1","t2","$","_c","undefined","t3","pressed","setPressed","rippleRef","state","growAnimation","rippleStartEvent","initialSize","rippleScale","t4","Symbol","for","isPrimary","startEvent","current","pointerId","isPressPointer","t5","event_0","buttons","shouldReactToEvent","t6","rect","height","width","maxDimension","Math","max","softEdgeSize","size","floor","hypotenuse","hypot","maxRadius","determineRippleSize","t7","rect_0","positionEvent","height_0","left","top","width_0","size_0","endPoint","x","y","origin","clientX","clientY","startPoint","getTranslationCoordinates","t8","target","positionEvent_0","ripple","cancel","rect_1","getBoundingClientRect","size_1","endPoint_0","startPoint_0","style","animate","transform","duration","long1","easing","standard","fill","startPressAnimation","t9","animation","elapsed","currentTime","Infinity","medium1","Promise","resolve","setTimeout","endPressAnimation","t10","getState","t11","event_1","target_0","currentTarget","_temp","handlePointerDownAsync","t12","event_2","handlePointerDown","t13","event_3","handlePointerUp","t14","event_4","handlePointerLeave","t15","event_5","handlePointerCancel","t16","event_6","handleClick","t17","handleContextMenu","onClickProp","onContextMenuProp","onPointerCancelProp","onPointerDownProp","onPointerLeaveProp","onPointerUpProp","t18","event_7","t19","event_8","t20","event_9","t21","event_10","t22","event_11","t23","event_12","t24","pointer","t25","t26","press","t27","t28","enabledResult","t29","disabledResult","resolve_0","short2"],"sources":["../../src/hooks/useRipple.tsx"],"sourcesContent":["import type { MouseEvent, MouseEventHandler, PointerEvent, PointerEventHandler, ReactNode } from 'react';\nimport * as stylex from '@stylexjs/stylex';\nimport { useCallback, useMemo, useRef, useState } from 'react';\nimport { rippleStyles } from '../styles/ripple';\nimport { motionDurationMs, motionEasing, spacingPx } from '../tokens/values';\n\n// Every timing this file drives is a motion token, spent at the point of use\n// below. They come from tokens/values rather than the StyleX theme because\n// element.animate() and setTimeout both reject a token's var() form, and the\n// same is true of the one geometry token: `PADDING` is added to a radius, and\n// a var() would concatenate rather than add. See src/styles/ripple.ts for the\n// opacity half of the mechanism, whose three timings are deliberately not\n// tokens.\n\n/** How far the ripple grows past the host's corners. `spacing.sm`. */\nconst PADDING = spacingPx.sm;\n\n// The rest are ratios and a pixel floor that no token group covers — spacing\n// is layout rhythm, and nothing in the set holds bare geometric ratios.\nconst INITIAL_ORIGIN_SCALE = 0.2;\nconst SOFT_EDGE_MINIMUM_SIZE = 75;\nconst SOFT_EDGE_CONTAINER_RATIO = 0.35;\n\n// Static input, so this is computed once for every consumer of the module\n// rather than once per component instance.\nconst surfaceProps = stylex.props(rippleStyles.surface);\n\n/**\n * On touch: `Inactive -> TouchDelay -> WaitingForClick -> Inactive`, or\n * `Inactive -> TouchDelay -> Holding -> WaitingForClick -> Inactive` for a\n * held press.\n *\n * On mouse or pen: `Inactive -> WaitingForClick -> Inactive`.\n */\nconst RippleState = {\n /** A touch has been confirmed as a press (held past the touch delay). */\n Holding: 2,\n /** No press in progress. Touch down moves to TouchDelay; mouse/pen down moves to WaitingForClick. */\n Inactive: 0,\n /** Touch down received; waiting to see if it's a tap or a scroll/swipe. */\n TouchDelay: 1,\n /** The press has finished growing; waiting for the click that ends it. */\n WaitingForClick: 3\n} as const;\ntype ReleaseHandlers<HostElement extends Element> = Omit<RippleEventHandlers<HostElement>, 'onClick'>;\ninterface RippleEventHandlers<HostElement extends Element> {\n onClick?: MouseEventHandler<HostElement>;\n onContextMenu?: MouseEventHandler<HostElement>;\n onPointerCancel?: PointerEventHandler<HostElement>;\n onPointerDown?: PointerEventHandler<HostElement>;\n onPointerLeave?: PointerEventHandler<HostElement>;\n onPointerUp?: PointerEventHandler<HostElement>;\n}\ntype RippleState = (typeof RippleState)[keyof typeof RippleState];\nfunction isTouch(event: PointerEvent) {\n return event.pointerType === 'touch';\n}\n\n/**\n * Whether the reader has asked the OS for less motion.\n *\n * Growth is a Web Animations call, which makes it the one animation in the\n * library no `@media (prefers-reduced-motion: reduce)` branch can reach — see\n * src/styles/ripple.ts for the opacity half, which is CSS and carries one.\n *\n * Read at the press rather than once at mount, so a reader who changes the\n * setting is answered by their next press rather than by their next reload.\n * The press already reads layout through `getBoundingClientRect`, which costs\n * more than this does.\n */\nfunction prefersReducedMotion() {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Renders a press ripple that grows from the pointer's position, or from\n * the element's center for a keyboard or other non-pointer activation.\n *\n * Growth runs via the Web Animations API on a single reused element (no\n * per-click DOM nodes to clean up), over a fixed duration independent of how\n * long the element is held — a real press-and-hold keeps the ripple\n * growing until release, while a quick tap is still held visible for a\n * minimum duration so it plays a complete animation rather than a flicker.\n *\n * Merges its own handlers with `externalHandlers` (e.g. a component's own\n * consumer-supplied props — ripple's own run first, then the external\n * ones) and returns `handlers` to spread onto the interactive element and\n * `surface`, the node to render as a child. The host element must\n * establish a positioning context (`position: relative` or similar) so\n * `surface`, which fills it via `inset: 0`, clips to its bounds and\n * inherits its shape.\n *\n * Pass `enabled: false` to opt out — no ripple listeners are attached and\n * no surface is rendered, leaving `externalHandlers` and a component's own\n * hover/press state layer (if any) untouched.\n *\n * Pass `endsOnRelease` for a host that never hears its own click: a\n * collection row, whose clicks React Aria's press handling keeps for itself.\n * The press then ends when the pointer is released over the host rather than\n * on the click that would follow, still held for the minimum a short press\n * gets. A keyboard press reaches such a host as no pointer event at all, so\n * it draws no ripple there.\n *\n * `handlers` and `surface` are hand-memoized (not left to build-tool\n * optimization) so a consumer rendering many instances — a list of icon\n * buttons, say — can memoize around them too, and so stability doesn't\n * depend on any particular compiler being configured.\n */\n// A host ending on the release never hears a click, so nothing is taken for\n// one and none is handed back: the handlers are the pointer ones alone, which\n// is also what a collection row's type admits.\nfunction useRipple<HostElement extends Element = Element>(enabled: boolean, externalHandlers: ReleaseHandlers<HostElement>, endsOnRelease: true): {\n handlers: ReleaseHandlers<HostElement>;\n surface: ReactNode;\n};\nfunction useRipple<HostElement extends Element = Element>(enabled?: boolean, externalHandlers?: RippleEventHandlers<HostElement>, endsOnRelease?: false): {\n handlers: RippleEventHandlers<HostElement>;\n surface: ReactNode;\n};\nfunction useRipple<HostElement extends Element = Element>(enabled = true, externalHandlers: RippleEventHandlers<HostElement> = {}, endsOnRelease = false): {\n handlers: RippleEventHandlers<HostElement>;\n surface: ReactNode;\n} {\n const [pressed, setPressed] = useState(false);\n const rippleRef = useRef<HTMLSpanElement>(null);\n const state = useRef<RippleState>(RippleState.Inactive);\n const growAnimation = useRef<Animation | undefined>(undefined);\n const rippleStartEvent = useRef<PointerEvent<HostElement> | undefined>(undefined);\n const initialSize = useRef(0);\n const rippleScale = useRef('1');\n\n // Whether `event` comes from the pointer a press would follow: the primary\n // one, and the one that started the press already in flight, if any.\n const isPressPointer = useCallback((event: PointerEvent<HostElement>) => {\n if (!event.isPrimary) {\n return false;\n }\n const startEvent = rippleStartEvent.current;\n return !startEvent || startEvent.pointerId === event.pointerId;\n }, []);\n const shouldReactToEvent = useCallback((event: PointerEvent<HostElement>) => isPressPointer(event) && (isTouch(event) || event.buttons === 1), [isPressPointer]);\n const determineRippleSize = useCallback((rect: DOMRect) => {\n const {\n height,\n width\n } = rect;\n const maxDimension = Math.max(height, width);\n const softEdgeSize = Math.max(SOFT_EDGE_CONTAINER_RATIO * maxDimension, SOFT_EDGE_MINIMUM_SIZE);\n const size = Math.floor(maxDimension * INITIAL_ORIGIN_SCALE);\n const hypotenuse = Math.hypot(width, height);\n const maxRadius = hypotenuse + PADDING;\n initialSize.current = size;\n rippleScale.current = `${(maxRadius + softEdgeSize) / size}`;\n return `${size}px`;\n }, []);\n const getTranslationCoordinates = useCallback((rect: DOMRect, positionEvent?: PointerEvent<HostElement>) => {\n const {\n height,\n left,\n top,\n width\n } = rect;\n const size = initialSize.current;\n const endPoint = {\n x: (width - size) / 2,\n y: (height - size) / 2\n };\n const origin = positionEvent ? {\n x: positionEvent.clientX - left,\n y: positionEvent.clientY - top\n } : {\n x: width / 2,\n y: height / 2\n };\n const startPoint = {\n x: origin.x - size / 2,\n y: origin.y - size / 2\n };\n return {\n endPoint,\n startPoint\n };\n }, []);\n const startPressAnimation = useCallback((target: HostElement, positionEvent?: PointerEvent<HostElement>) => {\n const ripple = rippleRef.current;\n if (!ripple) {\n return;\n }\n setPressed(true);\n growAnimation.current?.cancel();\n\n // Read once and share: the two helpers below both only need the\n // target's rect, and a second `getBoundingClientRect()` call back to\n // back with the first would be a redundant layout read.\n const rect = target.getBoundingClientRect();\n const size = determineRippleSize(rect);\n const {\n endPoint,\n startPoint\n } = getTranslationCoordinates(rect, positionEvent);\n ripple.style.width = size;\n ripple.style.height = size;\n growAnimation.current = ripple.animate({\n transform: [`translate(${startPoint.x}px, ${startPoint.y}px) scale(1)`, `translate(${endPoint.x}px, ${endPoint.y}px) scale(${rippleScale.current})`]\n }, {\n // Growth runs over a fixed duration regardless of how long the\n // press is held, so the token is spent here rather than named as a\n // constant — element.animate() is one of the two places a StyleX\n // token could not have gone.\n //\n // Zeroed rather than skipped under reduced motion, which lands the\n // disc at its full size with the growth never drawn. Skipping the\n // call outright would leave `growAnimation` unset, and the release\n // below reads its `currentTime` to decide whether the press has\n // been visible long enough — so the press would still be shown, and\n // would stop being held for its minimum.\n duration: prefersReducedMotion() ? 0 : motionDurationMs.long1,\n easing: motionEasing.standard,\n fill: 'forwards'\n });\n }, [determineRippleSize, getTranslationCoordinates]);\n const endPressAnimation = useCallback(async () => {\n rippleStartEvent.current = undefined;\n state.current = RippleState.Inactive;\n const animation = growAnimation.current;\n const elapsed = typeof animation?.currentTime === 'number' ? animation.currentTime : Infinity;\n\n // The floor on how briefly a ripple may be visible, so a quick tap reads\n // as a deliberate ripple rather than a flicker.\n if (elapsed >= motionDurationMs.medium1) {\n setPressed(false);\n return;\n }\n await new Promise(resolve => {\n setTimeout(resolve, motionDurationMs.medium1 - elapsed);\n });\n if (growAnimation.current !== animation) {\n // A newer press started; let it own the pressed state instead.\n return;\n }\n setPressed(false);\n }, []);\n\n // Reads through a function so a stale narrowing of `state.current` from\n // before the `await` below isn't (incorrectly) carried across it — the\n // ref can change via a different handler while this one is suspended.\n const getState = useCallback(() => state.current, []);\n const handlePointerDownAsync = useCallback(async (event: PointerEvent<HostElement>) => {\n if (!shouldReactToEvent(event)) {\n return;\n }\n rippleStartEvent.current = event;\n const target = event.currentTarget;\n if (!isTouch(event)) {\n state.current = RippleState.WaitingForClick;\n startPressAnimation(target, event);\n return;\n }\n\n // Delay so a scroll/swipe starting on the element doesn't flash a\n // ripple — only a held (or quickly released) touch counts as a press.\n state.current = RippleState.TouchDelay;\n await new Promise(resolve => {\n setTimeout(resolve, motionDurationMs.short2);\n });\n if (getState() !== RippleState.TouchDelay) {\n return;\n }\n state.current = RippleState.Holding;\n startPressAnimation(target, event);\n }, [getState, shouldReactToEvent, startPressAnimation]);\n const handlePointerDown = useCallback((event: PointerEvent<HostElement>) => {\n void handlePointerDownAsync(event);\n }, [handlePointerDownAsync]);\n const handlePointerUp = useCallback((event: PointerEvent<HostElement>) => {\n // A mouse or pen release carries no pressed button, so the guard the\n // other handlers share turns it away, which is right while a click\n // follows to end the press. A host ending on the release matches it by\n // its pointer alone.\n if (endsOnRelease && !isTouch(event)) {\n if (isPressPointer(event) && state.current === RippleState.WaitingForClick) {\n void endPressAnimation();\n }\n return;\n }\n if (!shouldReactToEvent(event)) {\n return;\n }\n if (state.current === RippleState.Holding) {\n state.current = RippleState.WaitingForClick;\n } else if (state.current === RippleState.TouchDelay) {\n // Released before the delay elapsed: treat as a completed tap.\n state.current = RippleState.WaitingForClick;\n startPressAnimation(event.currentTarget, rippleStartEvent.current);\n }\n\n // The release is as far as such a host hears, so it is where the\n // press ends — see `endsOnRelease` above.\n if (endsOnRelease && state.current === RippleState.WaitingForClick) {\n void endPressAnimation();\n }\n }, [endPressAnimation, endsOnRelease, isPressPointer, shouldReactToEvent, startPressAnimation]);\n const handlePointerLeave = useCallback((event: PointerEvent<HostElement>) => {\n if (isTouch(event) || !shouldReactToEvent(event)) {\n return;\n }\n if (state.current !== RippleState.Inactive) {\n void endPressAnimation();\n }\n }, [endPressAnimation, shouldReactToEvent]);\n const handlePointerCancel = useCallback((event: PointerEvent<HostElement>) => {\n if (!shouldReactToEvent(event)) {\n return;\n }\n void endPressAnimation();\n }, [endPressAnimation, shouldReactToEvent]);\n const handleClick = useCallback((event: MouseEvent<HostElement>) => {\n if (state.current === RippleState.WaitingForClick) {\n void endPressAnimation();\n return;\n }\n if (state.current === RippleState.Inactive) {\n // No pointerdown preceded this click — keyboard activation, a\n // programmatic `.click()`, or assistive-tech-synthesized activation.\n // Play a complete, centered press immediately.\n startPressAnimation(event.currentTarget);\n void endPressAnimation();\n }\n }, [endPressAnimation, startPressAnimation]);\n const handleContextMenu = useCallback(() => {\n void endPressAnimation();\n }, [endPressAnimation]);\n const {\n onClick: onClickProp,\n onContextMenu: onContextMenuProp,\n onPointerCancel: onPointerCancelProp,\n onPointerDown: onPointerDownProp,\n onPointerLeave: onPointerLeaveProp,\n onPointerUp: onPointerUpProp\n } = externalHandlers;\n const onClick = useCallback((event: MouseEvent<HostElement>) => {\n handleClick(event);\n onClickProp?.(event);\n }, [handleClick, onClickProp]);\n const onContextMenu = useCallback((event: MouseEvent<HostElement>) => {\n handleContextMenu();\n onContextMenuProp?.(event);\n }, [handleContextMenu, onContextMenuProp]);\n const onPointerCancel = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerCancel(event);\n onPointerCancelProp?.(event);\n }, [handlePointerCancel, onPointerCancelProp]);\n const onPointerDown = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerDown(event);\n onPointerDownProp?.(event);\n }, [handlePointerDown, onPointerDownProp]);\n const onPointerLeave = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerLeave(event);\n onPointerLeaveProp?.(event);\n }, [handlePointerLeave, onPointerLeaveProp]);\n const onPointerUp = useCallback((event: PointerEvent<HostElement>) => {\n handlePointerUp(event);\n onPointerUpProp?.(event);\n }, [handlePointerUp, onPointerUpProp]);\n const handlers = useMemo(() => {\n const pointer = {\n onContextMenu,\n onPointerCancel,\n onPointerDown,\n onPointerLeave,\n onPointerUp\n };\n return endsOnRelease ? pointer : {\n onClick,\n ...pointer\n };\n }, [endsOnRelease, onClick, onContextMenu, onPointerCancel, onPointerDown, onPointerLeave, onPointerUp]);\n const surface = useMemo(() => <span aria-hidden=\"true\" {...surfaceProps}>\n <span ref={rippleRef} {...stylex.props(rippleStyles.press, pressed && rippleStyles.pressed)} />\n </span>, [pressed]);\n\n // Two separate memos rather than one branching on `enabled`, so that\n // whichever branch is actually active stays keyed only on its own\n // inputs — the enabled result doesn't get a new identity every time\n // `externalHandlers` does (a component typically passes a fresh object\n // literal each render), and vice versa.\n const enabledResult = useMemo(() => ({\n handlers,\n surface\n }), [handlers, surface]);\n const disabledResult = useMemo(() => ({\n handlers: externalHandlers,\n surface: null\n }), [externalHandlers]);\n return enabled ? enabledResult : disabledResult;\n}\nexport { useRipple };"],"mappings":";;;;;;;;AAeA,MAAMc,UAAUD,UAAUE;AAI1B,MAAMC,uBAAuB;AAC7B,MAAMC,yBAAyB;AAC/B,MAAMC,4BAA4B;AAIlC,MAAMC,eAAed,MAAaK,OAAaW,OAAO;;;;;;;;AAStD,MAAMC,cAAc;;CAElBC,SAAS;;CAETC,UAAU;;CAEVC,YAAY;;CAEZC,iBAAiB;AACnB;AAWA,SAASa,QAAQC,OAAqB;CACpC,OAAOA,MAAMC,gBAAgB;AAC/B;;;;;;;;;;;;;AAcA,SAASC,uBAAuB;CAC9B,OAAOC,OAAOC,WAAW,kCAAkC,CAAC,CAACC;AAC/D;AA+CA,SAAAC,UAAAK,IAAAC,IAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,EAAA;CAA0D,MAAAR,UAAAI,OAAAK,KAAAA,IAAA,OAAAL;CAAc,IAAAM;CAAA,IAAAH,EAAA,OAAAF,IAAA;EAAEK,KAAAL,OAAAI,KAAAA,IAAA,CAAsD,IAAtDJ;EAAuDE,EAAA,KAAAF;EAAAE,EAAA,KAAAG;CAAA,OAAAA,KAAAH,EAAA;CAAvD,MAAAN,mBAAAS;CAAyD,MAAAR,gBAAAI,OAAAG,KAAAA,IAAA,QAAAH;CAIjI,MAAA,CAAAK,SAAAC,cAA8BlD,SAAS,KAAK;CAC5C,MAAAmD,YAAkBpD,OAAwB,IAAI;CAC9C,MAAAqD,QAAcrD,OAAoBc,YAAWE,QAAS;CACtD,MAAAsC,gBAAsBtD,OAA8BgD,KAAAA,CAAS;CAC7D,MAAAO,mBAAyBvD,OAA8CgD,KAAAA,CAAS;CAChF,MAAAQ,cAAoBxD,OAAO,CAAC;CAC5B,MAAAyD,cAAoBzD,OAAO,GAAG;CAAE,IAAA0D;CAAA,IAAAZ,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EAIGF,MAAA1B,UAAA;GACjC,IAAI,CAACA,MAAK6B,WAAU,OACX;GAET,MAAAC,aAAmBP,iBAAgBQ;GAAS,OACrC,CAACD,cAAcA,WAAUE,cAAehC,MAAKgC;EAAU;EAC/DlB,EAAA,KAAAY;CAAA,OAAAA,KAAAZ,EAAA;CAND,MAAAmB,iBAAuBP;CAMhB,IAAAQ;CAAA,IAAApB,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACgCM,MAAAC,YAAsCF,eAAejC,OAAgD,MAArCD,QAAQC,OAA4B,KAAlBA,QAAKoC,YAAa;EAAEtB,EAAA,KAAAoB;CAAA,OAAAA,KAAApB,EAAA;CAA7I,MAAAuB,qBAA2BH;CAAsI,IAAAI;CAAA,IAAAxB,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACzHU,MAAAC,SAAA;GACtC,MAAA,EAAAC,QAAAC,UAGIF;GACJ,MAAAG,eAAqBC,KAAIC,IAAKJ,QAAQC,KAAK;GAC3C,MAAAI,eAAqBF,KAAIC,IAAKlE,4BAA4BgE,cAAcjE,sBAAsB;GAC9F,MAAAqE,OAAaH,KAAII,MAAOL,eAAelE,oBAAoB;GAE3D,MAAA0E,YADmBP,KAAIM,MAAOR,OAAOD,MACnBQ,IAAa1E;GAC/BkD,YAAWO,UAAWe;GACtBrB,YAAWM,UAAW,IAAImB,YAAYL,gBAAgBC;GAAnC,OACZ,GAAGA,KAAI;EAAI;EACnBhC,EAAA,KAAAwB;CAAA,OAAAA,KAAAxB,EAAA;CAbD,MAAAqC,sBAA4Bb;CAarB,IAAAc;CAAA,IAAAtC,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACuCwB,MAAAC,QAAAC,kBAAA;GAC5C,MAAA,EAAAd,QAAAe,UAAAC,MAAAC,KAAAhB,OAAAiB,YAKInB;GACJ,MAAAoB,SAAanC,YAAWO;GACxB,MAAA6B,WAAiB;IAAAC,IACXpB,UAAQK,UAAQ;IAACgB,IACjBtB,WAASM,UAAQ;GACvB;GACA,MAAAiB,SAAeT,gBAAA;IAAAO,GACVP,cAAaU,UAAWR;IAAIM,GAC5BR,cAAaW,UAAWR;GAI7B,IANe;IAAAI,GAIVpB,UAAQ;IAACqB,GACTtB,WAAS;GACd;GAIE,OACK;IAAAoB;IAAAM,YAAAA;KAJYL,GACdE,OAAMF,IAAKf,SAAO;KAACgB,GACnBC,OAAMD,IAAKhB,SAAO;IAEhBoB;GAGP;EAAC;EACFpD,EAAA,KAAAsC;CAAA,OAAAA,KAAAtC,EAAA;CA3BD,MAAAqD,4BAAkCf;CA2B3B,IAAAgB;CAAA,IAAAtD,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACiCwC,MAAAC,QAAAC,oBAAA;GACtC,MAAAC,SAAenD,UAASW;GACxB,IAAI,CAACwC,QAAM;GAGXpD,WAAW,IAAI;GACfG,cAAaS,SAAgByC,OAAC;GAK9B,MAAAC,SAAaJ,OAAMK,sBAAuB;GAC1C,MAAAC,SAAaxB,oBAAoBZ,MAAI;GACrC,MAAA,EAAAqB,UAAAgB,YAAAV,YAAAW,iBAGIV,0BAA0B5B,QAAMe,eAAa;GACjDiB,OAAMO,MAAMrC,QAASK;GACrByB,OAAMO,MAAMtC,SAAUM;GACtBxB,cAAaS,UAAWwC,OAAMQ,QAAS,EAAAC,WAC1B,CAAC,aAAad,aAAUL,EAAE,MAAOK,aAAUJ,EAAE,eAAgB,aAAaF,WAAQC,EAAE,MAAOD,WAAQE,EAAE,YAAarC,YAAWM,QAAQ,EAAG,EACrJ,GAAG;IAAAkD,UAYS/E,qBAAkD,IAAlD,IAA6B/B,iBAAgB+G;IAAMC,QACrD/G,aAAYgH;IAASC,MACvB;GACR,CAAC;EAjBoB;EAkBtBvE,EAAA,KAAAsD;CAAA,OAAAA,KAAAtD,EAAA;CArCD,MAAAwE,sBAA4BlB;CAqCyB,IAAAmB;CAAA,IAAAzE,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACf2D,KAAA,YAAA;GACpChE,iBAAgBQ,UAAWf,KAAAA;GAC3BK,MAAKU,UAAWjD,YAAWE;GAC3B,MAAAwG,YAAkBlE,cAAaS;GAC/B,MAAA0D,UAAgB,OAAOD,WAASE,gBAAkB,WAAWF,UAASE,cAAtDC;GAIhB,IAAIF,WAAWtH,iBAAgByH,SAAQ;IACrCzE,WAAW,KAAK;IAAC;GAAA;GAGnB,MAAM,IAAI0E,SAAQC,YAAA;IAChBC,WAAWD,SAAS3H,iBAAgByH,UAAWH,OAAO;GAAC,CACxD;GACD,IAAInE,cAAaS,YAAayD,WAAS;GAIvCrE,WAAW,KAAK;EAAC;EAClBL,EAAA,KAAAyE;CAAA,OAAAA,KAAAzE,EAAA;CApBD,MAAAkF,oBAA0BT;CAoBnB,IAAAU;CAAA,IAAAnF,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EAKsBqE,YAAM5E,MAAKU;EAAQjB,EAAA,KAAAmF;CAAA,OAAAA,MAAAnF,EAAA;CAAhD,MAAAoF,WAAiBD;CAAqC,IAAAE;CAAA,IAAArF,EAAA,OAAAa,OAAAC,IAAA,2BAAA,GAAA;EACXuE,MAAA,OAAAC,YAAA;GACzC,IAAI,CAAC/D,mBAAmBrC,OAAK,GAAC;GAG9BuB,iBAAgBQ,UAAW/B;GAC3B,MAAAqG,WAAerG,QAAKsG;GACpB,IAAI,CAACvG,QAAQC,OAAK,GAAC;IACjBqB,MAAKU,UAAWjD,YAAWI;IAC3BoG,oBAAoBjB,UAAQrE,OAAK;IAAC;GAAA;GAMpCqB,MAAKU,UAAWjD,YAAWG;GAC3B,MAAM,IAAI4G,QAAQU,KAEjB;GACD,IAAIL,SAAS,MAAMpH,YAAWG,YAAW;GAGzCoC,MAAKU,UAAWjD,YAAWC;GAC3BuG,oBAAoBjB,UAAQrE,OAAK;EAAC;EACnCc,EAAA,KAAAqF;CAAA,OAAAA,MAAArF,EAAA;CAvBD,MAAA0F,yBAA+BL;CAuByB,IAAAM;CAAA,IAAA3F,EAAA,QAAAa,OAAAC,IAAA,2BAAA,GAAA;EAClB6E,OAAAC,YAAA;GAC/BF,uBAAuBxG,OAAK;EAAC;EACnCc,EAAA,MAAA2F;CAAA,OAAAA,MAAA3F,EAAA;CAFD,MAAA6F,oBAA0BF;CAEG,IAAAG;CAAA,IAAA9F,EAAA,QAAAL,eAAA;EACOmG,OAAAC,YAAA;GAKlC,IAAIpG,iBAAA,CAAkBV,QAAQC,OAAK,GAAC;IAClC,IAAIiC,eAAejC,OAAsD,KAA5CqB,MAAKU,YAAajD,YAAWI,iBACnD8G,kBAAkB;IACxB;GAAA;GAGH,IAAI,CAAC3D,mBAAmBrC,OAAK,GAAC;GAG9B,IAAIqB,MAAKU,YAAajD,YAAWC,SAC/BsC,MAAKU,UAAWjD,YAAWI;QACtB,IAAImC,MAAKU,YAAajD,YAAWG,YAAW;IAEjDoC,MAAKU,UAAWjD,YAAWI;IAC3BoG,oBAAoBtF,QAAKsG,eAAgB/E,iBAAgBQ,OAAQ;GAAC;GAKpE,IAAItB,iBAAiBY,MAAKU,YAAajD,YAAWI,iBAC3C8G,kBAAkB;EACxB;EACFlF,EAAA,MAAAL;EAAAK,EAAA,MAAA8F;CAAA,OAAAA,MAAA9F,EAAA;CA3BD,MAAAgG,kBAAwBF;CA2BwE,IAAAG;CAAA,IAAAjG,EAAA,QAAAa,OAAAC,IAAA,2BAAA,GAAA;EACzDmF,OAAAC,YAAA;GACrC,IAAIjH,QAAQC,OAAmC,KAA3C,CAAmBqC,mBAAmBrC,OAAK,GAAC;GAGhD,IAAIqB,MAAKU,YAAajD,YAAWE,UAC1BgH,kBAAkB;EACxB;EACFlF,EAAA,MAAAiG;CAAA,OAAAA,MAAAjG,EAAA;CAPD,MAAAmG,qBAA2BF;CAOiB,IAAAG;CAAA,IAAApG,EAAA,QAAAa,OAAAC,IAAA,2BAAA,GAAA;EACJsF,OAAAC,YAAA;GACtC,IAAI,CAAC9E,mBAAmBrC,OAAK,GAAC;GAGzBgG,kBAAkB;EAAC;EACzBlF,EAAA,MAAAoG;CAAA,OAAAA,MAAApG,EAAA;CALD,MAAAsG,sBAA4BF;CAKgB,IAAAG;CAAA,IAAAvG,EAAA,QAAAa,OAAAC,IAAA,2BAAA,GAAA;EACZyF,OAAAC,YAAA;GAC9B,IAAIjG,MAAKU,YAAajD,YAAWI,iBAAgB;IAC1C8G,kBAAkB;IAAC;GAAA;GAG1B,IAAI3E,MAAKU,YAAajD,YAAWE,UAAS;IAIxCsG,oBAAoBtF,QAAKsG,aAAc;IAClCN,kBAAkB;GAAC;EACzB;EACFlF,EAAA,MAAAuG;CAAA,OAAAA,MAAAvG,EAAA;CAZD,MAAAyG,cAAoBF;CAYyB,IAAAG;CAAA,IAAA1G,EAAA,QAAAa,OAAAC,IAAA,2BAAA,GAAA;EACP4F,YAAA;GAC/BxB,kBAAkB;EAAC;EACzBlF,EAAA,MAAA0G;CAAA,OAAAA,MAAA1G,EAAA;CAFD,MAAA2G,oBAA0BD;CAG1B,MAAA,EAAA/H,SAAAiI,aAAAhI,eAAAiI,mBAAAhI,iBAAAiI,qBAAAhI,eAAAiI,mBAAAhI,gBAAAiI,oBAAAhI,aAAAiI,oBAOIvH;CAAiB,IAAAwH;CAAA,IAAAlH,EAAA,QAAA4G,aAAA;EACOM,OAAAC,YAAA;GAC1BV,YAAYvH,OAAK;GACjB0H,cAAc1H,OAAK;EAAC;EACrBc,EAAA,MAAA4G;EAAA5G,EAAA,MAAAkH;CAAA,OAAAA,MAAAlH,EAAA;CAHD,MAAArB,UAAgBuI;CAGe,IAAAE;CAAA,IAAApH,EAAA,QAAA6G,mBAAA;EACGO,OAAAC,YAAA;GAChCV,kBAAkB;GAClBE,oBAAoB3H,OAAK;EAAC;EAC3Bc,EAAA,MAAA6G;EAAA7G,EAAA,MAAAoH;CAAA,OAAAA,MAAApH,EAAA;CAHD,MAAApB,gBAAsBwI;CAGqB,IAAAE;CAAA,IAAAtH,EAAA,QAAA8G,qBAAA;EACPQ,OAAAC,YAAA;GAClCjB,oBAAoBpH,OAAK;GACzB4H,sBAAsB5H,OAAK;EAAC;EAC7Bc,EAAA,MAAA8G;EAAA9G,EAAA,MAAAsH;CAAA,OAAAA,MAAAtH,EAAA;CAHD,MAAAnB,kBAAwByI;CAGuB,IAAAE;CAAA,IAAAxH,EAAA,QAAA+G,mBAAA;EACbS,OAAAC,aAAA;GAChC5B,kBAAkB3G,QAAK;GACvB6H,oBAAoB7H,QAAK;EAAC;EAC3Bc,EAAA,MAAA+G;EAAA/G,EAAA,MAAAwH;CAAA,OAAAA,MAAAxH,EAAA;CAHD,MAAAlB,gBAAsB0I;CAGqB,IAAAE;CAAA,IAAA1H,EAAA,QAAAgH,oBAAA;EACRU,OAAAC,aAAA;GACjCxB,mBAAmBjH,QAAK;GACxB8H,qBAAqB9H,QAAK;EAAC;EAC5Bc,EAAA,MAAAgH;EAAAhH,EAAA,MAAA0H;CAAA,OAAAA,MAAA1H,EAAA;CAHD,MAAAjB,iBAAuB2I;CAGsB,IAAAE;CAAA,IAAA5H,EAAA,QAAAgG,mBAAAhG,EAAA,QAAAiH,iBAAA;EACbW,OAAAC,aAAA;GAC9B7B,gBAAgB9G,QAAK;GACrB+H,kBAAkB/H,QAAK;EAAC;EACzBc,EAAA,MAAAgG;EAAAhG,EAAA,MAAAiH;EAAAjH,EAAA,MAAA4H;CAAA,OAAAA,MAAA5H,EAAA;CAHD,MAAAhB,cAAoB4I;CAGmB,IAAAE;CAAA,IAAA9H,EAAA,QAAApB,iBAAAoB,EAAA,QAAAnB,mBAAAmB,EAAA,QAAAlB,iBAAAkB,EAAA,QAAAjB,kBAAAiB,EAAA,QAAAhB,aAAA;EAErB8I,MAAA;GAAAlJ;GAAAC;GAAAC;GAAAC;GAAAC;EAMhB;EAACgB,EAAA,MAAApB;EAAAoB,EAAA,MAAAnB;EAAAmB,EAAA,MAAAlB;EAAAkB,EAAA,MAAAjB;EAAAiB,EAAA,MAAAhB;EAAAgB,EAAA,MAAA8H;CAAA,OAAAA,MAAA9H,EAAA;CAND,MAAA+H,UAAgBD;CAMd,IAAAE;CAAA,IAAAhI,EAAA,QAAAL,iBAAAK,EAAA,QAAArB,WAAAqB,EAAA,QAAA+H,SAAA;EACKC,MAAArI,gBAAAoI,UAAA;GAAApJ;GAAA,GAEFoJ;EACL;EAAC/H,EAAA,MAAAL;EAAAK,EAAA,MAAArB;EAAAqB,EAAA,MAAA+H;EAAA/H,EAAA,MAAAgI;CAAA,OAAAA,MAAAhI,EAAA;CAXH,MAAAJ,WAQEoI;CAIuG,IAAAC;CAAA,IAAAjI,EAAA,QAAAI,SAAA;EAEzE6H,MAAAlL,MAAaK,OAAY8K,OAAQ9H,WAAWhD,OAAYgD,OAAQ;EAACJ,EAAA,MAAAI;EAAAJ,EAAA,MAAAiI;CAAA,OAAAA,MAAAjI,EAAA;CAAA,IAAAmI;CAAA,IAAAnI,EAAA,QAAAiI,KAAA;EADnEE,MAAA,oBAAA,QAAA;GAAkB,eAAA;GAAM,GAAKtK;GACrD,UAAA,oBAAA,QAAA;IAAWyC,KAAAA;IAAS,GAAM2H;GAAiE,CAAA;EACtF,CAAA;EAAAjI,EAAA,MAAAiI;EAAAjI,EAAA,MAAAmI;CAAA,OAAAA,MAAAnI,EAAA;CAFX,MAAAjC,UAA8BoK;CAEN,IAAAC;CAAA,IAAApI,EAAA,QAAAJ,YAAAI,EAAA,QAAAjC,SAAA;EAOaqK,MAAA;GAAAxI;GAAA7B;EAGrC;EAACiC,EAAA,MAAAJ;EAAAI,EAAA,MAAAjC;EAAAiC,EAAA,MAAAoI;CAAA,OAAAA,MAAApI,EAAA;CAHD,MAAAqI,gBAAqCD;CAGZ,IAAAE;CAAA,IAAAtI,EAAA,QAAAN,kBAAA;EACa4I,MAAA;GAAA1I,UAC1BF;GAAgB3B,SACjB;EACX;EAACiC,EAAA,MAAAN;EAAAM,EAAA,MAAAsI;CAAA,OAAAA,MAAAtI,EAAA;CAAuB,OACjBP,UAAA4I,gBAAAE;AAAwC;AAnRjD,SAAA9C,MAAA+C,WAAA;CAgJMvD,WAAWD,WAAS3H,iBAAgBoL,MAAO;AAAC"}
|
package/dist/styles/overlay.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","names":["PopoverRenderProps","stylex","colors","motion","radii","shadows","spacing","FORCED_COLORS","fadeIn","scaleIn","overlay","fromBottom","k3nNDw","$$css","fromLeft","fromRight","fromTop","modalDialog","kZKoxP","kB7OPa","k1xSpc","kXwgrk","k3XXqK","popup","k44tkh","kKVMdj","kyAemX","kWkggS","kVAM5u","kaIpWk","ksu8eU","kMzoRj","kGVxlE","kMwMTN","kORKVm","popupDialog","kOIVth","scrim","kpwlN0","kVAEAm","origins","bottom","center","left","right","top","OverlayAlign","OverlaySide","placementOf","side","align","const","popupOrigin","placement"],"sources":["../../src/styles/overlay.ts"],"sourcesContent":["import type { PopoverRenderProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport '../tokens/design.tokens.stylex';\nimport { colors, motion, radii, shadows, spacing } from '../tokens/design.tokens.stylex';\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\n\n// What every overlay shares, drawn once. Popover's anchored surface and its\n// entry, Sheet's scrim, and the element that carries the dialog role inside\n// each of them; the coverage plan brings a dozen more overlays — Menu, Select,\n// ComboBox, Tooltip, the date pickers, Dialog — and each would otherwise have\n// written the same surface and the same scrim a second time. Geometry stays\n// with the component: how wide a popover is, which edge a sheet is pinned to,\n// where a dialog sits, are each overlay's own decision.\n//\n// Every one of these is portalled to the end of the body, which is why each\n// component takes a `container` prop and documents the same caveat: an app\n// that scopes its StyleX theme to a subtree has to point the portal inside it,\n// or the surface renders outside the theme and falls back to the tokens'\n// `prefers-color-scheme` default.\n//\n// Entry only, and no exit animation, for the same reason in every overlay:\n// React Aria keeps a closing surface mounted only while an animation is\n// running on it, and a popover in particular is dismissed far more often than\n// it is closed deliberately — usually by pressing something else, where a\n// lingering surface is in the way of whatever the press was for.\n\n// The scrim settles before the panel it sits behind arrives: shorter than\n// any panel's entry, so the two do not finish together.\nconst fadeIn = \"x18re5ia-B\";\n\n// An anchored surface grows from the edge it is anchored by rather than from\n// its own centre, which is what makes it read as coming out of the trigger.\n// The origin is a separate style, chosen from the placement React Aria\n// reports, so the same keyframes serve all four sides.\nconst scaleIn = \"x1k48ry3-B\";\nconst overlay = {\n fromBottom: {\n k3nNDw: \"x18ouj0k\",\n $$css: true\n },\n fromLeft: {\n k3nNDw: \"x1nf803f\",\n $$css: true\n },\n fromRight: {\n k3nNDw: \"xyibjs4\",\n $$css: true\n },\n fromTop: {\n k3nNDw: \"x1dp6rp6\",\n $$css: true\n },\n modalDialog: {\n kZKoxP: \"x5yr21d\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n k3XXqK: \"x1t137rt\",\n $$css: true\n },\n popup: {\n k44tkh: \"xvhm28k x1u6grsq\",\n kKVMdj: \"x97zbip\",\n kyAemX: \"x16dv9tl\",\n kWkggS: \"x1mjdul6\",\n kVAM5u: \"x1w1tqly\",\n kaIpWk: \"x62ce2h\",\n ksu8eU: \"xx61lck\",\n kMzoRj: \"x13rsnn2\",\n kGVxlE: \"x1os83gw\",\n kB7OPa: \"x9f619\",\n kMwMTN: \"x139gbkf\",\n kORKVm: \"x1odjw0f\",\n $$css: true\n },\n popupDialog: {\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kOIVth: \"x126z3so\",\n $$css: true\n },\n scrim: {\n k44tkh: \"x1vhuh8u\",\n kKVMdj: \"xqcmdr3\",\n kyAemX: \"x1yujl0p\",\n kWkggS: \"x1iqbvzf\",\n kpwlN0: \"x10a8y8t\",\n kVAEAm: \"xixxii4\",\n $$css: true\n }\n};\n\n// Which side the surface opened on, and the origin its entry grows from.\n// Keyed on the placement React Aria reports rather than the one asked for,\n// since the surface flips to the opposite side when there is no room on its\n// own; `center` is the placement React Aria reports for an anchor it could\n// not place beside, and grows from the top like the default.\nconst origins = {\n bottom: overlay.fromTop,\n center: overlay.fromTop,\n left: overlay.fromRight,\n right: overlay.fromLeft,\n top: overlay.fromBottom\n};\n\n/** Where along that side it lines up with the anchor. */\ntype OverlayAlign = 'center' | 'end' | 'start';\n\n/** Which side of the anchor a surface opens on. */\ntype OverlaySide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * React Aria's placement, from the side and the alignment a call site names.\n * Its own vocabulary pairs a side with `top`/`bottom` on the inline sides and\n * `start`/`end` on the block ones; a call site should not have to know which\n * of the two it is asking for, so this maps one onto the other.\n *\n * Shared by every anchored overlay rather than kept in one, since which side\n * a surface opens on is the same question for a popover, a menu and a\n * tooltip.\n */\nfunction placementOf(side: OverlaySide, align: OverlayAlign) {\n if (align === 'center') {\n return side;\n }\n if (side === 'top' || side === 'bottom') {\n return `${side} ${align}` as const;\n }\n return `${side} ${align === 'start' ? 'top' : 'bottom'}` as const;\n}\n\n/**\n * The origin an anchored surface grows from, for the placement React Aria\n * reports through its render state. `null`, before the surface has been\n * placed, grows from the top as `bottom` does.\n */\nfunction popupOrigin(placement: PopoverRenderProps['placement']) {\n return origins[placement ?? 'bottom'];\n}\nexport type { OverlayAlign, OverlaySide };\nexport { overlay, placementOf, popupOrigin };"],"mappings":";AAwCA,MAAMU,UAAU;CACdC,YAAY;EACVC,QAAQ;EACRC,OAAO;CACT;CACAC,UAAU;EACRF,QAAQ;EACRC,OAAO;CACT;CACAE,WAAW;EACTH,QAAQ;EACRC,OAAO;CACT;CACAG,SAAS;EACPJ,QAAQ;EACRC,OAAO;CACT;CACAI,aAAa;EACXC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRT,OAAO;CACT;CACAU,OAAO;EACLC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRb,QAAQ;EACRc,QAAQ;EACRC,QAAQ;EACRrB,OAAO;CACT;CACAsB,aAAa;EACXhB,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRe,QAAQ;EACRvB,OAAO;CACT;CACAwB,OAAO;EACLb,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;
|
|
1
|
+
{"version":3,"file":"overlay.js","names":["PopoverRenderProps","stylex","colors","motion","radii","shadows","spacing","FORCED_COLORS","fadeIn","scaleIn","overlay","fromBottom","k3nNDw","$$css","fromLeft","fromRight","fromTop","modalDialog","kZKoxP","kB7OPa","k1xSpc","kXwgrk","k3XXqK","popup","k44tkh","kKVMdj","kyAemX","kWkggS","kVAM5u","kaIpWk","ksu8eU","kMzoRj","kGVxlE","kMwMTN","kORKVm","popupDialog","kOIVth","scrim","kpwlN0","kVAEAm","origins","bottom","center","left","right","top","OverlayAlign","OverlaySide","placementOf","side","align","const","popupOrigin","placement"],"sources":["../../src/styles/overlay.ts"],"sourcesContent":["import type { PopoverRenderProps } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport '../tokens/design.tokens.stylex';\nimport { colors, motion, radii, shadows, spacing } from '../tokens/design.tokens.stylex';\n\n// Windows High Contrast and the rest of the forced-colours modes. Spelled\n// here rather than imported, for the reason src/field/styles.ts records: the\n// StyleX compiler resolves a constant across files only out of a `.stylex.ts`\n// module, and the generated one holds design tokens rather than queries.\nconst FORCED_COLORS = '@media (forced-colors: active)';\n\n// What every overlay shares, drawn once. Popover's anchored surface and its\n// entry, Sheet's scrim, and the element that carries the dialog role inside\n// each of them; the coverage plan brings a dozen more overlays — Menu, Select,\n// ComboBox, Tooltip, the date pickers, Dialog — and each would otherwise have\n// written the same surface and the same scrim a second time. Geometry stays\n// with the component: how wide a popover is, which edge a sheet is pinned to,\n// where a dialog sits, are each overlay's own decision.\n//\n// Every one of these is portalled to the end of the body, which is why each\n// component takes a `container` prop and documents the same caveat: an app\n// that scopes its StyleX theme to a subtree has to point the portal inside it,\n// or the surface renders outside the theme and falls back to the tokens'\n// `prefers-color-scheme` default.\n//\n// Entry only, and no exit animation, for the same reason in every overlay:\n// React Aria keeps a closing surface mounted only while an animation is\n// running on it, and a popover in particular is dismissed far more often than\n// it is closed deliberately — usually by pressing something else, where a\n// lingering surface is in the way of whatever the press was for.\n\n// The scrim settles before the panel it sits behind arrives: shorter than\n// any panel's entry, so the two do not finish together.\nconst fadeIn = \"x18re5ia-B\";\n\n// An anchored surface grows from the edge it is anchored by rather than from\n// its own centre, which is what makes it read as coming out of the trigger.\n// The origin is a separate style, chosen from the placement React Aria\n// reports, so the same keyframes serve all four sides.\nconst scaleIn = \"x1k48ry3-B\";\nconst overlay = {\n fromBottom: {\n k3nNDw: \"x18ouj0k\",\n $$css: true\n },\n fromLeft: {\n k3nNDw: \"x1nf803f\",\n $$css: true\n },\n fromRight: {\n k3nNDw: \"xyibjs4\",\n $$css: true\n },\n fromTop: {\n k3nNDw: \"x1dp6rp6\",\n $$css: true\n },\n modalDialog: {\n kZKoxP: \"x5yr21d\",\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n k3XXqK: \"x1t137rt\",\n $$css: true\n },\n popup: {\n k44tkh: \"xvhm28k x1u6grsq\",\n kKVMdj: \"x97zbip\",\n kyAemX: \"x16dv9tl\",\n kWkggS: \"x1mjdul6\",\n kVAM5u: \"x1w1tqly\",\n kaIpWk: \"x62ce2h\",\n ksu8eU: \"xx61lck\",\n kMzoRj: \"x13rsnn2\",\n kGVxlE: \"x1os83gw\",\n kB7OPa: \"x9f619\",\n kMwMTN: \"x139gbkf\",\n kORKVm: \"x1odjw0f\",\n $$css: true\n },\n popupDialog: {\n kB7OPa: \"x9f619\",\n k1xSpc: \"x78zum5\",\n kXwgrk: \"xdt5ytf\",\n kOIVth: \"x126z3so\",\n $$css: true\n },\n scrim: {\n k44tkh: \"x1vhuh8u\",\n kKVMdj: \"xqcmdr3\",\n kyAemX: \"x1yujl0p\",\n kWkggS: \"x1iqbvzf\",\n kB7OPa: \"x9f619\",\n kpwlN0: \"x10a8y8t\",\n kVAEAm: \"xixxii4\",\n $$css: true\n }\n};\n\n// Which side the surface opened on, and the origin its entry grows from.\n// Keyed on the placement React Aria reports rather than the one asked for,\n// since the surface flips to the opposite side when there is no room on its\n// own; `center` is the placement React Aria reports for an anchor it could\n// not place beside, and grows from the top like the default.\nconst origins = {\n bottom: overlay.fromTop,\n center: overlay.fromTop,\n left: overlay.fromRight,\n right: overlay.fromLeft,\n top: overlay.fromBottom\n};\n\n/** Where along that side it lines up with the anchor. */\ntype OverlayAlign = 'center' | 'end' | 'start';\n\n/** Which side of the anchor a surface opens on. */\ntype OverlaySide = 'bottom' | 'left' | 'right' | 'top';\n\n/**\n * React Aria's placement, from the side and the alignment a call site names.\n * Its own vocabulary pairs a side with `top`/`bottom` on the inline sides and\n * `start`/`end` on the block ones; a call site should not have to know which\n * of the two it is asking for, so this maps one onto the other.\n *\n * Shared by every anchored overlay rather than kept in one, since which side\n * a surface opens on is the same question for a popover, a menu and a\n * tooltip.\n */\nfunction placementOf(side: OverlaySide, align: OverlayAlign) {\n if (align === 'center') {\n return side;\n }\n if (side === 'top' || side === 'bottom') {\n return `${side} ${align}` as const;\n }\n return `${side} ${align === 'start' ? 'top' : 'bottom'}` as const;\n}\n\n/**\n * The origin an anchored surface grows from, for the placement React Aria\n * reports through its render state. `null`, before the surface has been\n * placed, grows from the top as `bottom` does.\n */\nfunction popupOrigin(placement: PopoverRenderProps['placement']) {\n return origins[placement ?? 'bottom'];\n}\nexport type { OverlayAlign, OverlaySide };\nexport { overlay, placementOf, popupOrigin };"],"mappings":";AAwCA,MAAMU,UAAU;CACdC,YAAY;EACVC,QAAQ;EACRC,OAAO;CACT;CACAC,UAAU;EACRF,QAAQ;EACRC,OAAO;CACT;CACAE,WAAW;EACTH,QAAQ;EACRC,OAAO;CACT;CACAG,SAAS;EACPJ,QAAQ;EACRC,OAAO;CACT;CACAI,aAAa;EACXC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRT,OAAO;CACT;CACAU,OAAO;EACLC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRb,QAAQ;EACRc,QAAQ;EACRC,QAAQ;EACRrB,OAAO;CACT;CACAsB,aAAa;EACXhB,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRe,QAAQ;EACRvB,OAAO;CACT;CACAwB,OAAO;EACLb,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRR,QAAQ;EACRmB,QAAQ;EACRC,QAAQ;EACR1B,OAAO;CACT;AACF;AAOA,MAAM2B,UAAU;CACdC,QAAQ/B,QAAQM;CAChB0B,QAAQhC,QAAQM;CAChB2B,MAAMjC,QAAQK;CACd6B,OAAOlC,QAAQI;CACf+B,KAAKnC,QAAQC;AACf;;;;;;;;;;;AAkBA,SAASqC,YAAYC,MAAmBC,OAAqB;CAC3D,IAAIA,UAAU,UACZ,OAAOD;CAET,IAAIA,SAAS,SAASA,SAAS,UAC7B,OAAO,GAAGA,KAAI,GAAIC;CAEpB,OAAO,GAAGD,KAAI,GAAIC,UAAU,UAAU,QAAQ;AAChD;;;;;;AAOA,SAASE,YAAYC,WAA4C;CAC/D,OAAOb,QAAQa,aAAa;AAC9B"}
|
package/dist/styles.css
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kanso-labs/kanso-ui",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.2",
|
|
4
4
|
"description": "A React component library built on React Aria Components primitives and styled with StyleX, with design tokens sourced from a single W3C DTCG file and compiled via Style Dictionary",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@commitlint/cli": "21.2.3",
|
|
75
75
|
"@commitlint/config-conventional": "21.2.3",
|
|
76
76
|
"@eslint/js": "10.0.1",
|
|
77
|
-
"@kanso-labs/unplugin-style-dictionary": "0.10.
|
|
77
|
+
"@kanso-labs/unplugin-style-dictionary": "0.10.6",
|
|
78
78
|
"@rolldown/plugin-babel": "0.2.4",
|
|
79
79
|
"@storybook/addon-a11y": "10.6.0",
|
|
80
80
|
"@storybook/addon-docs": "10.6.0",
|