@kushagradhawan/kookie-ui 0.1.78 → 0.1.79
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/components.css +69 -29
- package/dist/cjs/components/combobox.d.ts +57 -7
- package/dist/cjs/components/combobox.d.ts.map +1 -1
- package/dist/cjs/components/combobox.js +1 -1
- package/dist/cjs/components/combobox.js.map +3 -3
- package/dist/cjs/components/text-field.d.ts +2 -2
- package/dist/cjs/components/text-field.d.ts.map +1 -1
- package/dist/cjs/components/text-field.js +2 -2
- package/dist/cjs/components/text-field.js.map +3 -3
- package/dist/cjs/components/text-field.props.d.ts +26 -0
- package/dist/cjs/components/text-field.props.d.ts.map +1 -1
- package/dist/cjs/components/text-field.props.js +1 -1
- package/dist/cjs/components/text-field.props.js.map +1 -1
- package/dist/esm/components/combobox.d.ts +57 -7
- package/dist/esm/components/combobox.d.ts.map +1 -1
- package/dist/esm/components/combobox.js +1 -1
- package/dist/esm/components/combobox.js.map +3 -3
- package/dist/esm/components/text-field.d.ts +2 -2
- package/dist/esm/components/text-field.d.ts.map +1 -1
- package/dist/esm/components/text-field.js +2 -2
- package/dist/esm/components/text-field.js.map +3 -3
- package/dist/esm/components/text-field.props.d.ts +26 -0
- package/dist/esm/components/text-field.props.d.ts.map +1 -1
- package/dist/esm/components/text-field.props.js +1 -1
- package/dist/esm/components/text-field.props.js.map +1 -1
- package/package.json +2 -2
- package/schemas/base-button.json +1 -1
- package/schemas/button.json +1 -1
- package/schemas/icon-button.json +1 -1
- package/schemas/index.json +6 -6
- package/schemas/toggle-button.json +1 -1
- package/schemas/toggle-icon-button.json +1 -1
- package/src/components/combobox.css +56 -55
- package/src/components/combobox.tsx +305 -73
- package/src/components/text-field.css +83 -0
- package/src/components/text-field.props.tsx +28 -0
- package/src/components/text-field.tsx +222 -5
- package/styles.css +69 -29
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";"use client";var
|
|
1
|
+
"use strict";"use client";var $=Object.create;var k=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var te=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,oe=Object.prototype.hasOwnProperty;var ne=(t,o)=>{for(var r in o)k(t,r,{get:o[r],enumerable:!0})},U=(t,o,r,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let a of te(o))!oe.call(t,a)&&a!==r&&k(t,a,{get:()=>o[a],enumerable:!(d=ee(o,a))||d.enumerable});return t};var W=(t,o,r)=>(r=t!=null?$(re(t)):{},U(o||!t||!t.__esModule?k(r,"default",{value:t,enumerable:!0}):r,t)),se=t=>U(k({},"__esModule",{value:!0}),t);var le={};ne(le,{Root:()=>G,Slot:()=>_});module.exports=se(le);var e=W(require("react")),ie=W(require("react-dom")),X=W(require("classnames")),Y=require("radix-ui/internal"),N=require("./text-field.props.js"),q=require("../helpers/extract-props.js"),J=require("../props/margin.props.js");const G=e.forwardRef((t,o)=>{const r=e.useRef(null),{children:d,className:a,color:F,radius:M,panelBackground:R,material:E,style:w,...i}=(0,q.extractProps)(t,N.textFieldRootPropDefs,J.marginPropDefs),D=E||R,P=e.useId(),v=i.error||i.isInvalid,{"aria-describedby":S,"aria-labelledby":h}=i,b=e.useMemo(()=>{const p=[];return i.errorMessage&&p.push(P),S&&p.push(S),p.length>0?p.join(" "):void 0},[i.errorMessage,S,P]),x=e.useMemo(()=>({"aria-invalid":v,"aria-describedby":b,"aria-labelledby":h}),[v,b,h]),{error:z,errorMessage:C,isInvalid:H,required:y,"aria-describedby":f,"aria-labelledby":c,...T}=i,V=e.useCallback(p=>{const n=p.target;if(n.closest("input, button, a"))return;const l=r.current;if(!l)return;const s=n.closest(`
|
|
2
2
|
.rt-TextFieldSlot[data-side='right'],
|
|
3
3
|
.rt-TextFieldSlot:not([data-side='right']) ~ .rt-TextFieldSlot:not([data-side='left'])
|
|
4
|
-
`)?
|
|
4
|
+
`)?l.value.length:0;requestAnimationFrame(()=>{try{l.setSelectionRange(s,s)}catch{}l.focus()})},[]);return e.createElement("div",{"data-accent-color":F,"data-radius":M,"data-panel-background":D,"data-material":D,style:w,className:(0,X.default)("rt-TextFieldRoot",a,{"rt-error":v}),onPointerDown:V},e.createElement("input",{spellCheck:"false",...T,...x,ref:(0,Y.composeRefs)(r,o),className:"rt-reset rt-TextFieldInput"}),d,i.errorMessage&&e.createElement("div",{id:P,className:"rt-TextFieldErrorMessage",role:"alert","aria-live":"polite"},i.errorMessage))});G.displayName="TextField.Root";const _=e.forwardRef((t,o)=>{const{scrub:r,scrubValue:d,scrubStep:a=1,scrubSensitivity:F=1,scrubMin:M,scrubMax:R,scrubShiftMultiplier:E=10,scrubAltMultiplier:w=.1,onScrub:i,...D}=t,{className:P,color:v,side:S,...h}=(0,q.extractProps)(D,N.textFieldSlotPropDefs),b=e.useRef(null),[x,z]=e.useState(!1),[C,H]=e.useState({x:0,y:0}),y=e.useRef(0),f=e.useRef(0),c=e.useRef(0),T=e.useRef({scrubValue:d,scrubStep:a,scrubSensitivity:F,scrubMin:M,scrubMax:R,scrubShiftMultiplier:E,scrubAltMultiplier:w,onScrub:i});T.current={scrubValue:d,scrubStep:a,scrubSensitivity:F,scrubMin:M,scrubMax:R,scrubShiftMultiplier:E,scrubAltMultiplier:w,onScrub:i};const V=e.useCallback(n=>{if(!r||n.target.closest("input, button, a"))return;n.preventDefault(),y.current=0,f.current=d??0,c.current=n.clientX,H({x:n.clientX,y:n.clientY});const m=b.current;m&&m.requestPointerLock()},[r,d]);e.useEffect(()=>{const n=()=>{const l=document.pointerLockElement===b.current;z(l),l||(T.current.onScrub?.(0,!1),y.current=0,f.current=0)};return document.addEventListener("pointerlockchange",n),()=>{document.removeEventListener("pointerlockchange",n)}},[]),e.useEffect(()=>{if(!x)return;const n=m=>{const s=T.current,B=m.movementX,Q=m.movementY,I=window.innerWidth,L=window.innerHeight;c.current+=B,c.current>I?c.current=c.current%I:c.current<0&&(c.current=I+c.current%I),H(g=>{let u=g.y+Q;return u>L?u=u%L:u<0&&(u=L+u%L),{x:c.current,y:u}}),y.current+=B;const j=y.current/s.scrubSensitivity;if(Math.abs(j)>=1){let g=1;m.shiftKey?g=s.scrubShiftMultiplier:m.altKey&&(g=s.scrubAltMultiplier);const u=Math.trunc(j),A=u*s.scrubStep*g;let O=A;if(s.scrubMin!==void 0||s.scrubMax!==void 0){const Z=f.current+A,K=Math.max(s.scrubMin??-1/0,Math.min(s.scrubMax??1/0,Z));O=K-f.current,f.current=K}else f.current+=A;O!==0&&s.onScrub?.(O,!0),y.current=(j-u)*s.scrubSensitivity}},l=()=>{document.exitPointerLock()};return document.addEventListener("mousemove",n),document.addEventListener("mouseup",l),document.body.style.userSelect="none",()=>{document.removeEventListener("mousemove",n),document.removeEventListener("mouseup",l),document.body.style.userSelect=""}},[x]);const p=x?ie.createPortal(e.createElement("div",{className:"rt-TextFieldSlotScrubCursor",style:{position:"fixed",left:C.x,top:C.y,transform:"translate(-50%, -50%)",pointerEvents:"none",zIndex:99999},"aria-hidden":"true"}),document.body):null;return e.createElement("div",{"data-accent-color":v,"data-side":S,"data-scrub":r||void 0,"data-scrubbing":x||void 0,...h,ref:(0,Y.composeRefs)(b,o),className:(0,X.default)("rt-TextFieldSlot",P),onPointerDown:r?V:void 0},h.children,p)});_.displayName="TextField.Slot";
|
|
5
5
|
//# sourceMappingURL=text-field.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/text-field.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { composeRefs } from 'radix-ui/internal';\n\nimport { textFieldRootPropDefs, textFieldSlotPropDefs } from './text-field.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { NotInputTextualAttributes } from '../helpers/input-attributes.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype TextFieldRootElement = React.ElementRef<'input'>;\ntype TextFieldRootOwnProps = GetPropDefTypes<typeof textFieldRootPropDefs> & {\n defaultValue?: string | number;\n value?: string | number;\n type?:\n | 'date'\n | 'datetime-local'\n | 'email'\n | 'hidden'\n | 'month'\n | 'number'\n | 'password'\n | 'search'\n | 'tel'\n | 'text'\n | 'time'\n | 'url'\n | 'week';\n};\ntype TextFieldInputProps = ComponentPropsWithout<\n 'input',\n NotInputTextualAttributes | 'color' | 'defaultValue' | 'size' | 'type' | 'value'\n>;\ninterface TextFieldRootProps extends TextFieldInputProps, MarginProps, TextFieldRootOwnProps {}\nconst TextFieldRoot = React.forwardRef<TextFieldRootElement, TextFieldRootProps>(\n (props, forwardedRef) => {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const { children, className, color, radius, panelBackground, material, style, ...inputProps } =\n extractProps(props, textFieldRootPropDefs, marginPropDefs);\n const effectiveMaterial = material || panelBackground;\n\n // Generate unique IDs for accessibility\n const errorId = React.useId();\n\n // Determine invalid state\n const isInvalid = inputProps.error || inputProps.isInvalid;\n\n const { 'aria-describedby': ariaDescribedby, 'aria-labelledby': ariaLabelledby } = inputProps;\n\n // Build aria-describedby string\n const describedBy = React.useMemo(() => {\n const parts = [];\n if (inputProps.errorMessage) parts.push(errorId);\n if (ariaDescribedby) parts.push(ariaDescribedby);\n return parts.length > 0 ? parts.join(' ') : undefined;\n }, [inputProps.errorMessage, ariaDescribedby, errorId]);\n\n // Build aria attributes\n const ariaProps = React.useMemo(\n () => ({\n 'aria-invalid': isInvalid,\n 'aria-describedby': describedBy,\n 'aria-labelledby': ariaLabelledby,\n }),\n [isInvalid, describedBy, ariaLabelledby],\n );\n\n // Filter out our custom props to avoid DOM warnings\n const {\n error,\n errorMessage,\n isInvalid: _isInvalid,\n required,\n 'aria-describedby': _ariaDescribedby,\n 'aria-labelledby': _ariaLabelledby,\n ...nativeInputProps\n } = inputProps;\n\n // Memoized pointer event handler\n const handlePointerDown = React.useCallback((event: React.PointerEvent) => {\n const target = event.target as HTMLElement;\n if (target.closest('input, button, a')) return;\n\n const input = inputRef.current;\n if (!input) return;\n\n // Same selector as in the CSS to find the right slot\n const isRightSlot = target.closest(`\n .rt-TextFieldSlot[data-side='right'],\n .rt-TextFieldSlot:not([data-side='right']) ~ .rt-TextFieldSlot:not([data-side='left'])\n `);\n\n const cursorPosition = isRightSlot ? input.value.length : 0;\n\n requestAnimationFrame(() => {\n // Only some input types support this, browsers will throw an error if not supported\n // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange#:~:text=Note%20that%20according,not%20support%20selection%22.\n try {\n input.setSelectionRange(cursorPosition, cursorPosition);\n } catch {}\n input.focus();\n });\n }, []);\n\n return (\n <div\n data-accent-color={color}\n data-radius={radius}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n style={style}\n className={classNames('rt-TextFieldRoot', className, {\n 'rt-error': isInvalid,\n })}\n onPointerDown={handlePointerDown}\n >\n <input\n spellCheck=\"false\"\n {...nativeInputProps}\n {...ariaProps}\n ref={composeRefs(inputRef, forwardedRef)}\n className=\"rt-reset rt-TextFieldInput\"\n />\n {children}\n {inputProps.errorMessage && (\n <div id={errorId} className=\"rt-TextFieldErrorMessage\" role=\"alert\" aria-live=\"polite\">\n {inputProps.errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldRoot.displayName = 'TextField.Root';\n\ntype TextFieldSlotElement = React.ElementRef<'div'>;\ntype TextFieldSlotOwnProps = GetPropDefTypes<typeof textFieldSlotPropDefs>;\ninterface TextFieldSlotProps\n extends ComponentPropsWithout<'div', RemovedProps>,\n TextFieldSlotOwnProps {}\nconst TextFieldSlot = React.forwardRef<TextFieldSlotElement, TextFieldSlotProps>(\n (props, forwardedRef) => {\n const { className, color, side, ...slotProps } = extractProps(props, textFieldSlotPropDefs);\n return (\n <div\n data-accent-color={color}\n data-side={side}\n {...slotProps}\n ref={forwardedRef}\n className={classNames('rt-TextFieldSlot', className)}\n />\n );\n },\n);\nTextFieldSlot.displayName = 'TextField.Slot';\n\nexport { TextFieldRoot as Root, TextFieldSlot as Slot };\nexport type { TextFieldRootProps as RootProps, TextFieldSlotProps as SlotProps };\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["text_field_exports", "__export", "TextFieldRoot", "TextFieldSlot", "__toCommonJS", "React", "import_classnames", "import_internal", "import_text_field_props", "import_extract_props", "import_margin_props", "props", "forwardedRef", "inputRef", "children", "className", "color", "radius", "panelBackground", "material", "style", "inputProps", "effectiveMaterial", "errorId", "isInvalid", "ariaDescribedby", "ariaLabelledby", "describedBy", "parts", "ariaProps", "error", "errorMessage", "_isInvalid", "required", "_ariaDescribedby", "_ariaLabelledby", "nativeInputProps", "handlePointerDown", "event", "target", "input", "cursorPosition", "classNames", "side", "slotProps"]
|
|
4
|
+
"sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport classNames from 'classnames';\nimport { composeRefs } from 'radix-ui/internal';\n\nimport {\n textFieldRootPropDefs,\n textFieldSlotPropDefs,\n type TextFieldSlotScrubProps,\n} from './text-field.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { NotInputTextualAttributes } from '../helpers/input-attributes.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype TextFieldRootElement = React.ElementRef<'input'>;\ntype TextFieldRootOwnProps = GetPropDefTypes<typeof textFieldRootPropDefs> & {\n defaultValue?: string | number;\n value?: string | number;\n type?:\n | 'date'\n | 'datetime-local'\n | 'email'\n | 'hidden'\n | 'month'\n | 'number'\n | 'password'\n | 'search'\n | 'tel'\n | 'text'\n | 'time'\n | 'url'\n | 'week';\n};\ntype TextFieldInputProps = ComponentPropsWithout<\n 'input',\n NotInputTextualAttributes | 'color' | 'defaultValue' | 'size' | 'type' | 'value'\n>;\ninterface TextFieldRootProps extends TextFieldInputProps, MarginProps, TextFieldRootOwnProps {}\nconst TextFieldRoot = React.forwardRef<TextFieldRootElement, TextFieldRootProps>(\n (props, forwardedRef) => {\n const inputRef = React.useRef<HTMLInputElement>(null);\n const { children, className, color, radius, panelBackground, material, style, ...inputProps } =\n extractProps(props, textFieldRootPropDefs, marginPropDefs);\n const effectiveMaterial = material || panelBackground;\n\n // Generate unique IDs for accessibility\n const errorId = React.useId();\n\n // Determine invalid state\n const isInvalid = inputProps.error || inputProps.isInvalid;\n\n const { 'aria-describedby': ariaDescribedby, 'aria-labelledby': ariaLabelledby } = inputProps;\n\n // Build aria-describedby string\n const describedBy = React.useMemo(() => {\n const parts = [];\n if (inputProps.errorMessage) parts.push(errorId);\n if (ariaDescribedby) parts.push(ariaDescribedby);\n return parts.length > 0 ? parts.join(' ') : undefined;\n }, [inputProps.errorMessage, ariaDescribedby, errorId]);\n\n // Build aria attributes\n const ariaProps = React.useMemo(\n () => ({\n 'aria-invalid': isInvalid,\n 'aria-describedby': describedBy,\n 'aria-labelledby': ariaLabelledby,\n }),\n [isInvalid, describedBy, ariaLabelledby],\n );\n\n // Filter out our custom props to avoid DOM warnings\n const {\n error,\n errorMessage,\n isInvalid: _isInvalid,\n required,\n 'aria-describedby': _ariaDescribedby,\n 'aria-labelledby': _ariaLabelledby,\n ...nativeInputProps\n } = inputProps;\n\n // Memoized pointer event handler\n const handlePointerDown = React.useCallback((event: React.PointerEvent) => {\n const target = event.target as HTMLElement;\n if (target.closest('input, button, a')) return;\n\n const input = inputRef.current;\n if (!input) return;\n\n // Same selector as in the CSS to find the right slot\n const isRightSlot = target.closest(`\n .rt-TextFieldSlot[data-side='right'],\n .rt-TextFieldSlot:not([data-side='right']) ~ .rt-TextFieldSlot:not([data-side='left'])\n `);\n\n const cursorPosition = isRightSlot ? input.value.length : 0;\n\n requestAnimationFrame(() => {\n // Only some input types support this, browsers will throw an error if not supported\n // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange#:~:text=Note%20that%20according,not%20support%20selection%22.\n try {\n input.setSelectionRange(cursorPosition, cursorPosition);\n } catch {}\n input.focus();\n });\n }, []);\n\n return (\n <div\n data-accent-color={color}\n data-radius={radius}\n data-panel-background={effectiveMaterial}\n data-material={effectiveMaterial}\n style={style}\n className={classNames('rt-TextFieldRoot', className, {\n 'rt-error': isInvalid,\n })}\n onPointerDown={handlePointerDown}\n >\n <input\n spellCheck=\"false\"\n {...nativeInputProps}\n {...ariaProps}\n ref={composeRefs(inputRef, forwardedRef)}\n className=\"rt-reset rt-TextFieldInput\"\n />\n {children}\n {inputProps.errorMessage && (\n <div id={errorId} className=\"rt-TextFieldErrorMessage\" role=\"alert\" aria-live=\"polite\">\n {inputProps.errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldRoot.displayName = 'TextField.Root';\n\ntype TextFieldSlotElement = React.ElementRef<'div'>;\ntype TextFieldSlotOwnProps = GetPropDefTypes<typeof textFieldSlotPropDefs> & TextFieldSlotScrubProps;\ninterface TextFieldSlotProps\n extends ComponentPropsWithout<'div', RemovedProps>,\n TextFieldSlotOwnProps {}\nconst TextFieldSlot = React.forwardRef<TextFieldSlotElement, TextFieldSlotProps>(\n (props, forwardedRef) => {\n // Extract scrub props first (not part of PropDef system)\n const {\n scrub,\n scrubValue,\n scrubStep = 1,\n scrubSensitivity = 1,\n scrubMin,\n scrubMax,\n scrubShiftMultiplier = 10,\n scrubAltMultiplier = 0.1,\n onScrub,\n ...restProps\n } = props;\n\n // Then extract styling props\n const { className, color, side, ...slotProps } = extractProps(restProps, textFieldSlotPropDefs);\n\n const slotRef = React.useRef<HTMLDivElement>(null);\n const [isScrubbing, setIsScrubbing] = React.useState(false);\n // Virtual cursor position - X wraps around viewport, Y follows mouse\n const [cursorPosition, setCursorPosition] = React.useState({ x: 0, y: 0 });\n\n // Track accumulated sub-step movement for precision\n const accumulatedMovement = React.useRef(0);\n // Track current value for clamping (initialized to scrubValue when scrubbing starts)\n const currentValue = React.useRef(0);\n // Track virtual X position for wrap-around (separate from rendered position)\n const virtualX = React.useRef(0);\n\n // Store scrub config in refs so document handlers can access latest values\n const scrubConfigRef = React.useRef({\n scrubValue,\n scrubStep,\n scrubSensitivity,\n scrubMin,\n scrubMax,\n scrubShiftMultiplier,\n scrubAltMultiplier,\n onScrub,\n });\n scrubConfigRef.current = {\n scrubValue,\n scrubStep,\n scrubSensitivity,\n scrubMin,\n scrubMax,\n scrubShiftMultiplier,\n scrubAltMultiplier,\n onScrub,\n };\n\n const handlePointerDown = React.useCallback(\n (event: React.PointerEvent) => {\n if (!scrub) return;\n\n // Don't start scrubbing if clicking on interactive elements\n const target = event.target as HTMLElement;\n if (target.closest('input, button, a')) return;\n\n event.preventDefault();\n accumulatedMovement.current = 0;\n // Initialize to current value so min/max clamping works correctly\n currentValue.current = scrubValue ?? 0;\n\n // Initialize virtual cursor at actual mouse position\n virtualX.current = event.clientX;\n setCursorPosition({ x: event.clientX, y: event.clientY });\n\n // Request pointer lock for infinite movement (cursor won't hit screen edges)\n const slot = slotRef.current;\n if (slot) {\n slot.requestPointerLock();\n }\n },\n [scrub, scrubValue],\n );\n\n // Handle pointer lock state changes\n React.useEffect(() => {\n const handlePointerLockChange = () => {\n const isLocked = document.pointerLockElement === slotRef.current;\n setIsScrubbing(isLocked);\n if (!isLocked) {\n // Fire callback with isChanging = false when scrubbing ends\n scrubConfigRef.current.onScrub?.(0, false);\n accumulatedMovement.current = 0;\n currentValue.current = 0;\n }\n };\n\n document.addEventListener('pointerlockchange', handlePointerLockChange);\n return () => {\n document.removeEventListener('pointerlockchange', handlePointerLockChange);\n };\n }, []);\n\n // Attach document-level listeners when scrubbing starts\n React.useEffect(() => {\n if (!isScrubbing) return;\n\n const handleMouseMove = (event: MouseEvent) => {\n const config = scrubConfigRef.current;\n const movementX = event.movementX;\n const movementY = event.movementY;\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Update virtual position with wrap-around at viewport edges\n virtualX.current += movementX;\n if (virtualX.current > viewportWidth) {\n virtualX.current = virtualX.current % viewportWidth;\n } else if (virtualX.current < 0) {\n virtualX.current = viewportWidth + (virtualX.current % viewportWidth);\n }\n\n // Also track Y with wrap-around\n setCursorPosition((prev) => {\n let newY = prev.y + movementY;\n if (newY > viewportHeight) {\n newY = newY % viewportHeight;\n } else if (newY < 0) {\n newY = viewportHeight + (newY % viewportHeight);\n }\n return { x: virtualX.current, y: newY };\n });\n\n // Accumulate movement for sensitivity calculation\n accumulatedMovement.current += movementX;\n\n // Calculate how many steps we've moved\n const stepsFromMovement = accumulatedMovement.current / config.scrubSensitivity;\n\n if (Math.abs(stepsFromMovement) >= 1) {\n // Determine modifier multiplier\n let multiplier = 1;\n if (event.shiftKey) {\n multiplier = config.scrubShiftMultiplier;\n } else if (event.altKey) {\n multiplier = config.scrubAltMultiplier;\n }\n\n // Calculate delta\n const wholeSteps = Math.trunc(stepsFromMovement);\n const delta = wholeSteps * config.scrubStep * multiplier;\n\n // Apply min/max clamping if bounds are set\n let clampedDelta = delta;\n if (config.scrubMin !== undefined || config.scrubMax !== undefined) {\n const newValue = currentValue.current + delta;\n const clampedValue = Math.max(\n config.scrubMin ?? -Infinity,\n Math.min(config.scrubMax ?? Infinity, newValue),\n );\n clampedDelta = clampedValue - currentValue.current;\n currentValue.current = clampedValue;\n } else {\n currentValue.current += delta;\n }\n\n // Fire callback with clamped delta (isChanging = true during drag)\n if (clampedDelta !== 0) {\n config.onScrub?.(clampedDelta, true);\n }\n\n // Keep the fractional remainder for smooth sub-pixel accumulation\n accumulatedMovement.current = (stepsFromMovement - wholeSteps) * config.scrubSensitivity;\n }\n };\n\n const handleMouseUp = () => {\n // Exit pointer lock to end scrubbing\n document.exitPointerLock();\n };\n\n // Use mousemove for pointer lock (pointermove doesn't work well with pointer lock)\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n\n // Disable text selection during scrubbing\n document.body.style.userSelect = 'none';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n document.body.style.userSelect = '';\n };\n }, [isScrubbing]);\n\n // Render virtual cursor via portal to body so it's not clipped\n const virtualCursor = isScrubbing\n ? ReactDOM.createPortal(\n <div\n className=\"rt-TextFieldSlotScrubCursor\"\n style={{\n position: 'fixed',\n left: cursorPosition.x,\n top: cursorPosition.y,\n transform: 'translate(-50%, -50%)',\n pointerEvents: 'none',\n zIndex: 99999,\n }}\n aria-hidden=\"true\"\n />,\n document.body,\n )\n : null;\n\n return (\n <div\n data-accent-color={color}\n data-side={side}\n data-scrub={scrub || undefined}\n data-scrubbing={isScrubbing || undefined}\n {...slotProps}\n ref={composeRefs(slotRef, forwardedRef)}\n className={classNames('rt-TextFieldSlot', className)}\n onPointerDown={scrub ? handlePointerDown : undefined}\n >\n {slotProps.children}\n {virtualCursor}\n </div>\n );\n },\n);\nTextFieldSlot.displayName = 'TextField.Slot';\n\nexport { TextFieldRoot as Root, TextFieldSlot as Slot };\nexport type { TextFieldRootProps as RootProps, TextFieldSlotProps as SlotProps };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["text_field_exports", "__export", "TextFieldRoot", "TextFieldSlot", "__toCommonJS", "React", "ReactDOM", "import_classnames", "import_internal", "import_text_field_props", "import_extract_props", "import_margin_props", "props", "forwardedRef", "inputRef", "children", "className", "color", "radius", "panelBackground", "material", "style", "inputProps", "effectiveMaterial", "errorId", "isInvalid", "ariaDescribedby", "ariaLabelledby", "describedBy", "parts", "ariaProps", "error", "errorMessage", "_isInvalid", "required", "_ariaDescribedby", "_ariaLabelledby", "nativeInputProps", "handlePointerDown", "event", "target", "input", "cursorPosition", "classNames", "scrub", "scrubValue", "scrubStep", "scrubSensitivity", "scrubMin", "scrubMax", "scrubShiftMultiplier", "scrubAltMultiplier", "onScrub", "restProps", "side", "slotProps", "slotRef", "isScrubbing", "setIsScrubbing", "setCursorPosition", "accumulatedMovement", "currentValue", "virtualX", "scrubConfigRef", "slot", "handlePointerLockChange", "isLocked", "handleMouseMove", "config", "movementX", "movementY", "viewportWidth", "viewportHeight", "prev", "newY", "stepsFromMovement", "multiplier", "wholeSteps", "delta", "clampedDelta", "newValue", "clampedValue", "handleMouseUp", "virtualCursor"]
|
|
7
7
|
}
|
|
@@ -96,5 +96,31 @@ declare const textFieldSlotPropDefs: {
|
|
|
96
96
|
values: readonly ["left", "right"];
|
|
97
97
|
};
|
|
98
98
|
};
|
|
99
|
+
/** Scrubbing props for TextField.Slot - handled separately from PropDef system */
|
|
100
|
+
interface TextFieldSlotScrubProps {
|
|
101
|
+
/** Enable scrubbing behavior on this slot */
|
|
102
|
+
scrub?: boolean;
|
|
103
|
+
/** Current value (required for min/max clamping to work correctly) */
|
|
104
|
+
scrubValue?: number;
|
|
105
|
+
/** Base value change per movement unit (default: 1) */
|
|
106
|
+
scrubStep?: number;
|
|
107
|
+
/** Pixels of movement per step - higher = less sensitive (default: 1) */
|
|
108
|
+
scrubSensitivity?: number;
|
|
109
|
+
/** Minimum allowed value */
|
|
110
|
+
scrubMin?: number;
|
|
111
|
+
/** Maximum allowed value */
|
|
112
|
+
scrubMax?: number;
|
|
113
|
+
/** Step multiplier when Shift is held (default: 10) */
|
|
114
|
+
scrubShiftMultiplier?: number;
|
|
115
|
+
/** Step multiplier when Alt/Option is held (default: 0.1) */
|
|
116
|
+
scrubAltMultiplier?: number;
|
|
117
|
+
/**
|
|
118
|
+
* Callback fired during scrubbing with the value delta
|
|
119
|
+
* @param delta - The change in value
|
|
120
|
+
* @param isChanging - true while dragging, false when released
|
|
121
|
+
*/
|
|
122
|
+
onScrub?: (delta: number, isChanging: boolean) => void;
|
|
123
|
+
}
|
|
124
|
+
export type { TextFieldSlotScrubProps };
|
|
99
125
|
export { textFieldRootPropDefs, textFieldSlotPropDefs };
|
|
100
126
|
//# sourceMappingURL=text-field.props.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-field.props.d.ts","sourceRoot":"","sources":["../../../src/components/text-field.props.tsx"],"names":[],"mappings":"AAYA,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B1B,CAAC;AAIF,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAa1B,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"text-field.props.d.ts","sourceRoot":"","sources":["../../../src/components/text-field.props.tsx"],"names":[],"mappings":"AAYA,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0B1B,CAAC;AAIF,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAa1B,CAAC;AAEF,kFAAkF;AAClF,UAAU,uBAAuB;IAC/B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,6DAA6D;IAC7D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;CACxD;AAED,YAAY,EAAE,uBAAuB,EAAE,CAAC;AAExC,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var a=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(r,e)=>{for(var t in e)a(r,t,{get:e[t],enumerable:!0})},y=(r,e,t,p)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of b(e))!c.call(r,s)&&s!==t&&a(r,s,{get:()=>e[s],enumerable:!(p=d(e,s))||p.enumerable});return r};var g=r=>y(a({},"__esModule",{value:!0}),r);var M={};m(M,{textFieldRootPropDefs:()=>f,textFieldSlotPropDefs:()=>u});module.exports=g(M);var n=require("../props/color.prop.js"),o=require("../props/padding.props.js"),i=require("../props/radius.prop.js"),l=require("./flex.props.js");const P=["1","2","3"],D=["classic","surface","soft","ghost","outline"],v=["solid","translucent"],x=["solid","translucent"],f={size:{type:"enum",className:"rt-r-size",values:P,default:"2",responsive:!0},variant:{type:"enum",className:"rt-variant",values:D,default:"surface"},error:{type:"boolean",default:!1},errorMessage:{type:"string",default:void 0},isInvalid:{type:"boolean",default:!1},required:{type:"boolean",default:!1},"aria-describedby":{type:"string",default:void 0},"aria-labelledby":{type:"string",default:void 0},...n.colorPropDef,...i.radiusPropDef,panelBackground:{type:"enum",values:v,default:void 0},material:{type:"enum",values:x,default:void 0}},S=["left","right"],u={side:{type:"enum",values:S},...n.colorPropDef,gap:l.flexPropDefs.gap,px:o.paddingPropDefs.px,pl:o.paddingPropDefs.pl,pr:o.paddingPropDefs.pr};
|
|
2
2
|
//# sourceMappingURL=text-field.props.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/text-field.props.tsx"],
|
|
4
|
-
"sourcesContent": ["import { colorPropDef } from '../props/color.prop.js';\nimport { paddingPropDefs } from '../props/padding.props.js';\nimport { radiusPropDef } from '../props/radius.prop.js';\nimport { flexPropDefs } from './flex.props.js';\n\nimport type { PropDef } from '../props/prop-def.js';\n\nconst sizes = ['1', '2', '3'] as const;\nconst variants = ['classic', 'surface', 'soft', 'ghost', 'outline'] as const;\nconst panelBackgrounds = ['solid', 'translucent'] as const;\nconst materials = ['solid', 'translucent'] as const;\n\nconst textFieldRootPropDefs = {\n size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true },\n variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' },\n // Error and validation props\n error: { type: 'boolean', default: false },\n errorMessage: { type: 'string', default: undefined },\n isInvalid: { type: 'boolean', default: false },\n required: { type: 'boolean', default: false },\n // Accessibility props\n 'aria-describedby': { type: 'string', default: undefined },\n 'aria-labelledby': { type: 'string', default: undefined },\n ...colorPropDef,\n ...radiusPropDef,\n panelBackground: { type: 'enum', values: panelBackgrounds, default: undefined },\n material: { type: 'enum', values: materials, default: undefined },\n} satisfies {\n size: PropDef<(typeof sizes)[number]>;\n variant: PropDef<(typeof variants)[number]>;\n error: PropDef<boolean>;\n errorMessage: PropDef<string | undefined>;\n isInvalid: PropDef<boolean>;\n required: PropDef<boolean>;\n 'aria-describedby': PropDef<string | undefined>;\n 'aria-labelledby': PropDef<string | undefined>;\n panelBackground: PropDef<(typeof panelBackgrounds)[number] | undefined>;\n material: PropDef<(typeof materials)[number] | undefined>;\n};\n\nconst sides = ['left', 'right'] as const;\n\nconst textFieldSlotPropDefs = {\n side: { type: 'enum', values: sides },\n ...colorPropDef,\n gap: flexPropDefs.gap,\n px: paddingPropDefs.px,\n pl: paddingPropDefs.pl,\n pr: paddingPropDefs.pr,\n} satisfies {\n side: PropDef<(typeof sides)[number]>;\n gap: typeof flexPropDefs.gap;\n px: typeof paddingPropDefs.px;\n pl: typeof paddingPropDefs.pl;\n pr: typeof paddingPropDefs.pr;\n};\n\nexport { textFieldRootPropDefs, textFieldSlotPropDefs };\n"],
|
|
4
|
+
"sourcesContent": ["import { colorPropDef } from '../props/color.prop.js';\nimport { paddingPropDefs } from '../props/padding.props.js';\nimport { radiusPropDef } from '../props/radius.prop.js';\nimport { flexPropDefs } from './flex.props.js';\n\nimport type { PropDef } from '../props/prop-def.js';\n\nconst sizes = ['1', '2', '3'] as const;\nconst variants = ['classic', 'surface', 'soft', 'ghost', 'outline'] as const;\nconst panelBackgrounds = ['solid', 'translucent'] as const;\nconst materials = ['solid', 'translucent'] as const;\n\nconst textFieldRootPropDefs = {\n size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '2', responsive: true },\n variant: { type: 'enum', className: 'rt-variant', values: variants, default: 'surface' },\n // Error and validation props\n error: { type: 'boolean', default: false },\n errorMessage: { type: 'string', default: undefined },\n isInvalid: { type: 'boolean', default: false },\n required: { type: 'boolean', default: false },\n // Accessibility props\n 'aria-describedby': { type: 'string', default: undefined },\n 'aria-labelledby': { type: 'string', default: undefined },\n ...colorPropDef,\n ...radiusPropDef,\n panelBackground: { type: 'enum', values: panelBackgrounds, default: undefined },\n material: { type: 'enum', values: materials, default: undefined },\n} satisfies {\n size: PropDef<(typeof sizes)[number]>;\n variant: PropDef<(typeof variants)[number]>;\n error: PropDef<boolean>;\n errorMessage: PropDef<string | undefined>;\n isInvalid: PropDef<boolean>;\n required: PropDef<boolean>;\n 'aria-describedby': PropDef<string | undefined>;\n 'aria-labelledby': PropDef<string | undefined>;\n panelBackground: PropDef<(typeof panelBackgrounds)[number] | undefined>;\n material: PropDef<(typeof materials)[number] | undefined>;\n};\n\nconst sides = ['left', 'right'] as const;\n\nconst textFieldSlotPropDefs = {\n side: { type: 'enum', values: sides },\n ...colorPropDef,\n gap: flexPropDefs.gap,\n px: paddingPropDefs.px,\n pl: paddingPropDefs.pl,\n pr: paddingPropDefs.pr,\n} satisfies {\n side: PropDef<(typeof sides)[number]>;\n gap: typeof flexPropDefs.gap;\n px: typeof paddingPropDefs.px;\n pl: typeof paddingPropDefs.pl;\n pr: typeof paddingPropDefs.pr;\n};\n\n/** Scrubbing props for TextField.Slot - handled separately from PropDef system */\ninterface TextFieldSlotScrubProps {\n /** Enable scrubbing behavior on this slot */\n scrub?: boolean;\n /** Current value (required for min/max clamping to work correctly) */\n scrubValue?: number;\n /** Base value change per movement unit (default: 1) */\n scrubStep?: number;\n /** Pixels of movement per step - higher = less sensitive (default: 1) */\n scrubSensitivity?: number;\n /** Minimum allowed value */\n scrubMin?: number;\n /** Maximum allowed value */\n scrubMax?: number;\n /** Step multiplier when Shift is held (default: 10) */\n scrubShiftMultiplier?: number;\n /** Step multiplier when Alt/Option is held (default: 0.1) */\n scrubAltMultiplier?: number;\n /**\n * Callback fired during scrubbing with the value delta\n * @param delta - The change in value\n * @param isChanging - true while dragging, false when released\n */\n onScrub?: (delta: number, isChanging: boolean) => void;\n}\n\nexport type { TextFieldSlotScrubProps };\n\nexport { textFieldRootPropDefs, textFieldSlotPropDefs };\n"],
|
|
5
5
|
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,2BAAAE,EAAA,0BAAAC,IAAA,eAAAC,EAAAJ,GAAA,IAAAK,EAA6B,kCAC7BC,EAAgC,qCAChCC,EAA8B,mCAC9BC,EAA6B,2BAI7B,MAAMC,EAAQ,CAAC,IAAK,IAAK,GAAG,EACtBC,EAAW,CAAC,UAAW,UAAW,OAAQ,QAAS,SAAS,EAC5DC,EAAmB,CAAC,QAAS,aAAa,EAC1CC,EAAY,CAAC,QAAS,aAAa,EAEnCV,EAAwB,CAC5B,KAAM,CAAE,KAAM,OAAQ,UAAW,YAAa,OAAQO,EAAO,QAAS,IAAK,WAAY,EAAK,EAC5F,QAAS,CAAE,KAAM,OAAQ,UAAW,aAAc,OAAQC,EAAU,QAAS,SAAU,EAEvF,MAAO,CAAE,KAAM,UAAW,QAAS,EAAM,EACzC,aAAc,CAAE,KAAM,SAAU,QAAS,MAAU,EACnD,UAAW,CAAE,KAAM,UAAW,QAAS,EAAM,EAC7C,SAAU,CAAE,KAAM,UAAW,QAAS,EAAM,EAE5C,mBAAoB,CAAE,KAAM,SAAU,QAAS,MAAU,EACzD,kBAAmB,CAAE,KAAM,SAAU,QAAS,MAAU,EACxD,GAAG,eACH,GAAG,gBACH,gBAAiB,CAAE,KAAM,OAAQ,OAAQC,EAAkB,QAAS,MAAU,EAC9E,SAAU,CAAE,KAAM,OAAQ,OAAQC,EAAW,QAAS,MAAU,CAClE,EAaMC,EAAQ,CAAC,OAAQ,OAAO,EAExBV,EAAwB,CAC5B,KAAM,CAAE,KAAM,OAAQ,OAAQU,CAAM,EACpC,GAAG,eACH,IAAK,eAAa,IAClB,GAAI,kBAAgB,GACpB,GAAI,kBAAgB,GACpB,GAAI,kBAAgB,EACtB",
|
|
6
6
|
"names": ["text_field_props_exports", "__export", "textFieldRootPropDefs", "textFieldSlotPropDefs", "__toCommonJS", "import_color_prop", "import_padding_props", "import_radius_prop", "import_flex_props", "sizes", "variants", "panelBackgrounds", "materials", "sides"]
|
|
7
7
|
}
|
|
@@ -14,6 +14,14 @@ import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-p
|
|
|
14
14
|
import type { GetPropDefTypes } from '../props/prop-def.js';
|
|
15
15
|
type TextFieldVariant = (typeof textFieldRootPropDefs.variant.values)[number];
|
|
16
16
|
type ComboboxValue = string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Custom filter function for Combobox search.
|
|
19
|
+
* @param value - The item's value being tested
|
|
20
|
+
* @param search - The current search string
|
|
21
|
+
* @param keywords - Optional keywords associated with the item
|
|
22
|
+
* @returns A number between 0 and 1 where 0 means no match and 1 means exact match.
|
|
23
|
+
* Fractional values indicate relevance for sorting.
|
|
24
|
+
*/
|
|
17
25
|
type CommandFilter = (value: string, search: string, keywords?: string[]) => number;
|
|
18
26
|
/**
|
|
19
27
|
* Additional props supported by Combobox.Root beyond the Radix Popover surface.
|
|
@@ -34,6 +42,42 @@ type ComboboxRootOwnProps = GetPropDefTypes<typeof comboboxRootPropDefs> & {
|
|
|
34
42
|
shouldFilter?: boolean;
|
|
35
43
|
loop?: boolean;
|
|
36
44
|
disabled?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to reset the search value when an option is selected.
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
resetSearchOnSelect?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Accent color for the combobox trigger and content.
|
|
52
|
+
*/
|
|
53
|
+
color?: (typeof comboboxTriggerPropDefs.color.values)[number];
|
|
54
|
+
/**
|
|
55
|
+
* Display value shown in the trigger. This is the recommended approach for
|
|
56
|
+
* best performance as it avoids needing to mount items to register labels.
|
|
57
|
+
*
|
|
58
|
+
* Can be either:
|
|
59
|
+
* - A string: Static display value
|
|
60
|
+
* - A function: `(value: string | null) => string | undefined` - Called with current value
|
|
61
|
+
*
|
|
62
|
+
* Use this when:
|
|
63
|
+
* - You have the selected item's label available (e.g., from your data source)
|
|
64
|
+
* - Items haven't mounted yet (e.g., on initial render with a defaultValue)
|
|
65
|
+
* - You want optimal performance with forceMount={false} (default)
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Static string
|
|
69
|
+
* <Combobox.Root value="usa" displayValue="United States">
|
|
70
|
+
*
|
|
71
|
+
* // Function (recommended for dynamic data)
|
|
72
|
+
* <Combobox.Root
|
|
73
|
+
* value={selectedCountry}
|
|
74
|
+
* displayValue={(value) => countries.find(c => c.code === value)?.name}
|
|
75
|
+
* >
|
|
76
|
+
*
|
|
77
|
+
* If not provided, falls back to the label registered by the selected item
|
|
78
|
+
* (requires forceMount={true}), then to the raw value.
|
|
79
|
+
*/
|
|
80
|
+
displayValue?: string | ((value: ComboboxValue) => string | undefined);
|
|
37
81
|
};
|
|
38
82
|
type PopoverRootProps = React.ComponentPropsWithoutRef<typeof Popover.Root>;
|
|
39
83
|
interface ComboboxRootProps extends PopoverRootProps, ComboboxRootOwnProps {
|
|
@@ -58,6 +102,8 @@ interface ComboboxValueProps extends React.ComponentPropsWithoutRef<'span'> {
|
|
|
58
102
|
/**
|
|
59
103
|
* Value mirrors Select.Value by showing the selected item's label
|
|
60
104
|
* or falling back to placeholder text supplied by the consumer or context.
|
|
105
|
+
*
|
|
106
|
+
* Priority: resolvedDisplayValue (explicit) > selectedLabel (from items) > raw value > children > placeholder
|
|
61
107
|
*/
|
|
62
108
|
declare const ComboboxValue: React.ForwardRefExoticComponent<ComboboxValueProps & React.RefAttributes<HTMLSpanElement>>;
|
|
63
109
|
type ComboboxContentOwnProps = GetPropDefTypes<typeof comboboxContentPropDefs> & {
|
|
@@ -70,10 +116,14 @@ interface ComboboxContentProps extends Omit<ComponentPropsWithout<typeof Popover
|
|
|
70
116
|
* and instantiating cmdk's Command list for roving focus + filtering.
|
|
71
117
|
*/
|
|
72
118
|
declare const ComboboxContent: React.ForwardRefExoticComponent<ComboboxContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
73
|
-
interface ComboboxInputProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> {
|
|
119
|
+
interface ComboboxInputProps extends Omit<React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>, 'value' | 'onValueChange'> {
|
|
74
120
|
startAdornment?: React.ReactNode;
|
|
75
121
|
endAdornment?: React.ReactNode;
|
|
76
122
|
variant?: TextFieldVariant;
|
|
123
|
+
/** Controlled search value. Falls back to Root's searchValue if not provided. */
|
|
124
|
+
value?: string;
|
|
125
|
+
/** Callback when search value changes. Falls back to Root's onSearchValueChange if not provided. */
|
|
126
|
+
onValueChange?: (value: string) => void;
|
|
77
127
|
}
|
|
78
128
|
/**
|
|
79
129
|
* Input composes TextField tokens with cmdk's Command.Input to provide
|
|
@@ -84,6 +134,7 @@ interface ComboboxListProps extends React.ComponentPropsWithoutRef<typeof Comman
|
|
|
84
134
|
}
|
|
85
135
|
/**
|
|
86
136
|
* List wraps cmdk's Command.List to inherit base menu styles and provides ScrollArea for the items.
|
|
137
|
+
* Also handles aria-activedescendant tracking via a single MutationObserver for all items.
|
|
87
138
|
*/
|
|
88
139
|
declare const ComboboxList: React.ForwardRefExoticComponent<ComboboxListProps & React.RefAttributes<HTMLDivElement>>;
|
|
89
140
|
interface ComboboxEmptyProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> {
|
|
@@ -107,14 +158,13 @@ interface ComboboxSeparatorProps extends React.ComponentPropsWithoutRef<typeof C
|
|
|
107
158
|
* Separator visually divides logical sections of the option list.
|
|
108
159
|
*/
|
|
109
160
|
declare const ComboboxSeparator: React.ForwardRefExoticComponent<ComboboxSeparatorProps & React.RefAttributes<HTMLDivElement>>;
|
|
110
|
-
interface ComboboxItemProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item> {
|
|
161
|
+
interface ComboboxItemProps extends Omit<React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>, 'keywords'> {
|
|
162
|
+
/** Display label for the item. Also used for search unless keywords are provided. */
|
|
111
163
|
label?: string;
|
|
164
|
+
/** Additional keywords for search filtering (overrides automatic label-based search). */
|
|
165
|
+
keywords?: string[];
|
|
112
166
|
}
|
|
113
|
-
/**
|
|
114
|
-
* Item wires cmdk's selection handling with Kookie UI tokens and
|
|
115
|
-
* ensures labels are registered for displaying the current value.
|
|
116
|
-
*/
|
|
117
167
|
declare const ComboboxItem: React.ForwardRefExoticComponent<ComboboxItemProps & React.RefAttributes<HTMLDivElement>>;
|
|
118
168
|
export { ComboboxRoot as Root, ComboboxTrigger as Trigger, ComboboxValue as Value, ComboboxContent as Content, ComboboxInput as Input, ComboboxList as List, ComboboxEmpty as Empty, ComboboxGroup as Group, ComboboxLabel as Label, ComboboxSeparator as Separator, ComboboxItem as Item, };
|
|
119
|
-
export type { ComboboxRootProps as RootProps, ComboboxTriggerProps as TriggerProps, ComboboxContentProps as ContentProps, ComboboxInputProps as InputProps, ComboboxListProps as ListProps, ComboboxEmptyProps as EmptyProps, ComboboxGroupProps as GroupProps, ComboboxLabelProps as LabelProps, ComboboxSeparatorProps as SeparatorProps, ComboboxItemProps as ItemProps, };
|
|
169
|
+
export type { ComboboxRootProps as RootProps, ComboboxTriggerProps as TriggerProps, ComboboxValueProps as ValueProps, ComboboxContentProps as ContentProps, ComboboxInputProps as InputProps, ComboboxListProps as ListProps, ComboboxEmptyProps as EmptyProps, ComboboxGroupProps as GroupProps, ComboboxLabelProps as LabelProps, ComboboxSeparatorProps as SeparatorProps, ComboboxItemProps as ItemProps, };
|
|
120
170
|
//# sourceMappingURL=combobox.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../src/components/combobox.tsx"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAC;AAGnD,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAK7G,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAGxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,KAAK,gBAAgB,GAAG,CAAC,OAAO,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAC9E,KAAK,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;AACnC,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;AAEpF;;GAEG;AACH,KAAK,oBAAoB,GAAG,eAAe,CAAC,OAAO,oBAAoB,CAAC,GAAG;IACzE,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../../src/components/combobox.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import*as
|
|
1
|
+
"use client";import*as e from"react";import d from"classnames";import{useControllableState as G}from"radix-ui/internal";import{Command as E}from"cmdk";import{extractProps as Y}from"../helpers/extract-props.js";import{comboboxRootPropDefs as M,comboboxTriggerPropDefs as de,comboboxContentPropDefs as w}from"./combobox.props.js";import{marginPropDefs as ue}from"../props/margin.props.js";import{ChevronDownIcon as Ce,ThickCheckIcon as fe}from"./icons.js";import{Theme as xe,useThemeContext as ge}from"./theme.js";import{requireReactElement as Pe}from"../helpers/require-react-element.js";import*as B from"./popover.js";import{ScrollArea as ve}from"./scroll-area.js";import{Slottable as he}from"./slot.js";import"./text-field.props.js";const Z=e.createContext(null),R=t=>{const r=e.useContext(Z);if(!r)throw new Error(`${t} must be used within Combobox.Root`);return r},ee=e.createContext(null),oe=()=>e.useContext(ee),te=t=>{const{children:r,size:o=M.size.default,highContrast:n=M.highContrast.default,value:i,defaultValue:a=null,onValueChange:s,open:p,defaultOpen:b=!1,onOpenChange:l,placeholder:m="Select an option",searchPlaceholder:g="Search options...",searchValue:u,defaultSearchValue:C="",onSearchValueChange:f,filter:c,shouldFilter:v=!0,loop:x=!0,disabled:V,resetSearchOnSelect:h=!0,color:S,displayValue:I,...T}=t,$=`combobox-listbox-${e.useId()}`,[j,H]=e.useState(void 0),[z,N]=G({prop:p,defaultProp:b,onChange:l}),[P,L]=G({prop:i,defaultProp:a,onChange:s}),[q,D]=G({prop:u,defaultProp:C,onChange:f}),k=e.useRef(new Map),[K,F]=e.useState(void 0),_=e.useCallback((y,X)=>{k.current.set(y,X),y===P&&F(X)},[P]),J=e.useCallback(y=>{k.current.delete(y)},[]);e.useEffect(()=>{if(P!=null){const y=k.current.get(P);F(y)}else F(void 0)},[P]);const Q=e.useCallback(y=>{L(y),N(!1),h&&D("")},[N,D,L,h]);e.useEffect(()=>{},[P]);const U=e.useMemo(()=>{if(I!=null)return typeof I=="function"?I(P):I},[I,P]),ce=e.useMemo(()=>({size:o,highContrast:n,placeholder:m,searchPlaceholder:g,filter:c,shouldFilter:v,loop:x,disabled:V,resetSearchOnSelect:h,color:S,resolvedDisplayValue:U,open:z,setOpen:N,value:P,setValue:L,searchValue:q,setSearchValue:D,selectedLabel:K,registerItemLabel:_,unregisterItemLabel:J,handleSelect:Q,listboxId:$,activeDescendantId:j,setActiveDescendantId:H}),[o,n,m,g,c,v,x,V,h,S,U,z,N,P,L,q,D,K,_,J,Q,$,j,H]);return e.createElement(Z.Provider,{value:ce},e.createElement(B.Root,{open:z,onOpenChange:N,...T},r))};te.displayName="Combobox.Root";const re=e.forwardRef((t,r)=>{const o=R("Combobox.Trigger"),{children:n,className:i,placeholder:a,disabled:s,readOnly:p,error:b,loading:l,color:m,radius:g,...u}=Y({size:o.size,highContrast:o.highContrast,...t},{size:M.size,highContrast:M.highContrast},de,ue),{material:C,panelBackground:f}=t,c=s??o.disabled,v=m??o.color,x=e.useMemo(()=>({role:"combobox","aria-expanded":o.open,"aria-disabled":c||void 0,"aria-haspopup":"listbox","aria-controls":o.open?o.listboxId:void 0,"aria-activedescendant":o.open?o.activeDescendantId:void 0,"aria-autocomplete":"list"}),[o.open,o.listboxId,o.activeDescendantId,c]),V=e.createElement(e.Fragment,null,e.createElement("span",{className:"rt-SelectTriggerInner"},e.createElement(W,{placeholder:a??o.placeholder})),l?e.createElement("div",{className:"rt-SelectIcon rt-SelectLoadingIcon","aria-hidden":"true"},e.createElement("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none"},e.createElement("circle",{cx:"8",cy:"8",r:"6.5",stroke:"currentColor",strokeWidth:"1",strokeLinecap:"round",strokeDasharray:"6 34",strokeDashoffset:"0",className:"rt-SelectLoadingSpinner"}))):e.createElement(Ce,{className:"rt-SelectIcon"})),{type:h,...S}=u,T=e.createElement("button",{"data-accent-color":v,"data-radius":g,"data-panel-background":f,"data-material":C,"data-error":b,"data-loading":l,"data-disabled":c||void 0,"data-read-only":p||void 0,...S,...x,type:h??"button",disabled:c,ref:r,className:d("rt-reset","rt-SelectTrigger","rt-ComboboxTrigger",i)},n?Pe(n):V);return e.createElement(B.Trigger,{disabled:c},T)});re.displayName="Combobox.Trigger";const W=e.forwardRef(({placeholder:t,children:r,className:o,...n},i)=>{const a=R("Combobox.Value"),s=a.resolvedDisplayValue??a.selectedLabel??a.value??void 0,p=t??a.placeholder;return e.createElement("span",{...n,ref:i,className:d("rt-ComboboxValue",o)},s??r??p)});W.displayName="Combobox.Value";const ne=e.forwardRef((t,r)=>{const o=R("Combobox.Content"),n=ge(),i=n.panelBackground,a=t.size??o.size??w.size.default,s=t.variant??w.variant.default,p=t.highContrast??o.highContrast??w.highContrast.default,{className:b,children:l,color:m,forceMount:g,container:u,...C}=Y({...t,size:a,variant:s,highContrast:p},w),f=m||o.color||n.accentColor,c=e.useMemo(()=>typeof a!="string"?b:b?.split(/\s+/).filter(Boolean).filter(x=>!/^rt-r-size-\d$/.test(x)).join(" ")||void 0,[b,a]),v=g===!0?!0:void 0;return e.createElement(B.Content,{size:a,"data-accent-color":f,"data-material":i,"data-panel-background":i,align:"start",sideOffset:4,collisionPadding:10,...C,forceMount:v,container:u,ref:r,className:d("rt-PopperContent","rt-BaseMenuContent","rt-ComboboxContent",c)},e.createElement(xe,{asChild:!0},e.createElement(ee.Provider,{value:{variant:s,size:String(a),color:f,material:i,highContrast:p}},e.createElement(E,{loop:o.loop,shouldFilter:o.shouldFilter,filter:o.filter,className:"rt-ComboboxCommand"},l))))});ne.displayName="Combobox.Content";const ae=e.forwardRef(({className:t,startAdornment:r,endAdornment:o,placeholder:n,variant:i,value:a,onValueChange:s,...p},b)=>{const l=R("Combobox.Input"),m=oe(),g=m?.variant??"solid",u=m?.color,C=m?.material,f=i??(g==="solid"?"surface":"soft"),c=a??l.searchValue,v=s??l.setSearchValue,x=e.createElement("div",{className:d("rt-TextFieldRoot","rt-ComboboxInputRoot",`rt-r-size-${l.size}`,`rt-variant-${f}`),"data-accent-color":u,"data-material":C,"data-panel-background":C},r?e.createElement("div",{className:"rt-TextFieldSlot"},r):null,e.createElement(E.Input,{...p,ref:b,value:c,onValueChange:v,placeholder:n??l.searchPlaceholder,className:d("rt-reset","rt-TextFieldInput",t)}),o?e.createElement("div",{className:"rt-TextFieldSlot","data-side":"right"},o):null);return m?e.createElement("div",{className:"rt-ComboboxSearch"},x):x});ae.displayName="Combobox.Input";const se=e.forwardRef(({className:t,...r},o)=>{const n=R("Combobox.List"),i=e.useRef(null),a=e.useCallback(s=>{i.current=s,typeof o=="function"?o(s):o&&(o.current=s)},[o]);return e.useEffect(()=>{const s=i.current;if(!s)return;const p=()=>{const m=s.querySelector('[data-selected="true"], [aria-selected="true"]')?.id;n.setActiveDescendantId(m||void 0)};p();const b=new MutationObserver(p);return b.observe(s,{attributes:!0,attributeFilter:["data-selected","aria-selected"],subtree:!0}),()=>b.disconnect()},[n.setActiveDescendantId]),e.createElement(ve,{type:"auto",className:"rt-ComboboxScrollArea",scrollbars:"vertical",size:"1"},e.createElement("div",{className:d("rt-BaseMenuViewport","rt-ComboboxViewport")},e.createElement(E.List,{...r,ref:a,id:n.listboxId,role:"listbox","aria-label":"Options",className:d("rt-ComboboxList",t)})))});se.displayName="Combobox.List";const ie=e.forwardRef(({className:t,...r},o)=>e.createElement(E.Empty,{...r,ref:o,className:d("rt-ComboboxEmpty",t)}));ie.displayName="Combobox.Empty";const le=e.forwardRef(({className:t,...r},o)=>e.createElement(E.Group,{...r,ref:o,className:d("rt-BaseMenuGroup","rt-ComboboxGroup",t)}));le.displayName="Combobox.Group";const me=e.forwardRef(({className:t,...r},o)=>e.createElement("div",{...r,ref:o,className:d("rt-BaseMenuLabel","rt-ComboboxLabel",t)}));me.displayName="Combobox.Label";const pe=e.forwardRef(({className:t,...r},o)=>e.createElement(E.Separator,{...r,ref:o,className:d("rt-BaseMenuSeparator","rt-ComboboxSeparator",t)}));pe.displayName="Combobox.Separator";function A(t){if(typeof t=="string")return t;if(typeof t=="number")return String(t);if(t==null||typeof t=="boolean")return"";if(Array.isArray(t))return t.map(A).filter(Boolean).join(" ");if(e.isValidElement(t)){const r=t.props;if(r.children)return A(r.children)}return""}const be=e.forwardRef(({className:t,children:r,label:o,value:n,disabled:i,onSelect:a,keywords:s,...p},b)=>{const l=R("Combobox.Item"),m=oe(),g=e.useMemo(()=>A(r),[r]),u=o??(g||String(n)),C=n!=null&&l.value===n,f=m?.size?`rt-r-size-${m.size}`:void 0,c=s??[u],x=`combobox-item-${e.useId()}`,{registerItemLabel:V,unregisterItemLabel:h,handleSelect:S}=l;e.useEffect(()=>{if(n)return V(n,u),()=>h(n)},[V,h,n,u]);const I=e.useCallback(O=>{S(O),a?.(O)},[S,a]),T=i??l.disabled??!1;return e.createElement(E.Item,{...p,id:x,value:n,keywords:c,role:"option","aria-selected":C,...T?{disabled:!0,"aria-disabled":!0}:{},ref:b,onSelect:I,className:d("rt-reset","rt-BaseMenuItem","rt-ComboboxItem",t)},C?e.createElement("span",{className:d("rt-BaseMenuItemIndicator","rt-ComboboxItemIndicator",f)},e.createElement(fe,{className:d("rt-BaseMenuItemIndicatorIcon","rt-ComboboxItemIndicatorIcon",f)})):null,e.createElement(he,null,r))});be.displayName="Combobox.Item";export{ne as Content,ie as Empty,le as Group,ae as Input,be as Item,me as Label,se as List,te as Root,pe as Separator,re as Trigger,W as Value};
|
|
2
2
|
//# sourceMappingURL=combobox.js.map
|