@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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/combobox.tsx"],
|
|
4
|
-
"sourcesContent": ["'use client';\n\n/**\n * Combobox is a compound component built on top of Popover and cmdk's Command list.\n * It mirrors the Select API while adding search-first behaviors including filtering,\n * async-friendly state management, and design token support for trigger, content,\n * and input variants.\n */\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { useControllableState } from 'radix-ui/internal';\nimport { Command as CommandPrimitive } from 'cmdk';\n\nimport { extractProps } from '../helpers/extract-props.js';\nimport { comboboxRootPropDefs, comboboxTriggerPropDefs, comboboxContentPropDefs } from './combobox.props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { ChevronDownIcon, ThickCheckIcon } from './icons.js';\nimport { Theme, useThemeContext } from './theme.js';\nimport { requireReactElement } from '../helpers/require-react-element.js';\nimport * as Popover from './popover.js';\nimport { ScrollArea } from './scroll-area.js';\nimport { Slottable } from './slot.js';\nimport { textFieldRootPropDefs } from './text-field.props.js';\n\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype TextFieldVariant = (typeof textFieldRootPropDefs.variant.values)[number];\ntype ComboboxValue = string | null;\ntype CommandFilter = (value: string, search: string, keywords?: string[]) => number;\n\n/**\n * Additional props supported by Combobox.Root beyond the Radix Popover surface.\n */\ntype ComboboxRootOwnProps = GetPropDefTypes<typeof comboboxRootPropDefs> & {\n value?: ComboboxValue;\n defaultValue?: ComboboxValue;\n onValueChange?: (value: ComboboxValue) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n placeholder?: string;\n searchPlaceholder?: string;\n searchValue?: string;\n defaultSearchValue?: string;\n onSearchValueChange?: (value: string) => void;\n filter?: CommandFilter;\n shouldFilter?: boolean;\n loop?: boolean;\n disabled?: boolean;\n};\n\n/**\n * Internal context shared by all sub-components to avoid prop drilling.\n */\ninterface ComboboxContextValue extends ComboboxRootOwnProps {\n open: boolean;\n setOpen: (open: boolean) => void;\n value: ComboboxValue;\n setValue: (value: ComboboxValue) => void;\n searchValue: string;\n setSearchValue: (value: string) => void;\n selectedLabel?: string;\n registerItemLabel: (value: string, label: string) => void;\n handleSelect: (value: string) => void;\n}\n\nconst ComboboxContext = React.createContext<ComboboxContextValue | null>(null);\n\n/**\n * Utility hook that ensures consumers are wrapped in Combobox.Root.\n */\nconst useComboboxContext = (caller: string) => {\n const ctx = React.useContext(ComboboxContext);\n if (!ctx) {\n throw new Error(`${caller} must be used within Combobox.Root`);\n }\n return ctx;\n};\n\n/**\n * Context for values that are only available inside Content (e.g., variant, color)\n * so that Input/Item can style themselves consistently.\n */\nconst ComboboxContentContext = React.createContext<{ variant: 'solid' | 'soft'; size?: string; color?: string; material?: string; highContrast?: boolean } | null>(null);\nconst useComboboxContentContext = () => {\n const ctx = React.useContext(ComboboxContentContext);\n return ctx; // Optional - Input might not always be in Content\n};\n\ntype PopoverRootProps = React.ComponentPropsWithoutRef<typeof Popover.Root>;\ninterface ComboboxRootProps extends PopoverRootProps, ComboboxRootOwnProps {}\n/**\n * Root component that wires up Popover behavior, controllable state,\n * and shared context for trigger/content/input sub-components.\n */\nconst ComboboxRoot: React.FC<ComboboxRootProps> = (props) => {\n const {\n children,\n size = comboboxRootPropDefs.size.default,\n highContrast = comboboxRootPropDefs.highContrast.default,\n value: valueProp,\n defaultValue = null,\n onValueChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n placeholder = 'Select an option',\n searchPlaceholder = 'Search options...',\n searchValue: searchValueProp,\n defaultSearchValue = '',\n onSearchValueChange,\n filter,\n shouldFilter = true,\n loop = true,\n disabled,\n ...rootProps\n } = props;\n\n const [open, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n\n const [value, setValue] = useControllableState<ComboboxValue>({\n prop: valueProp,\n defaultProp: defaultValue,\n onChange: onValueChange,\n });\n\n const [searchValue, setSearchValue] = useControllableState<string>({\n prop: searchValueProp,\n defaultProp: defaultSearchValue,\n onChange: onSearchValueChange,\n });\n\n const labelMapRef = React.useRef(new Map<string, string>());\n const registerItemLabel = React.useCallback((itemValue: string, label: string) => {\n labelMapRef.current.set(itemValue, label);\n }, []);\n\n const selectedLabel = value != null ? labelMapRef.current.get(value) : undefined;\n\n const handleSelect = React.useCallback(\n (nextValue: string) => {\n setValue(nextValue);\n setOpen(false);\n setSearchValue('');\n },\n [setOpen, setSearchValue, setValue],\n );\n\n const contextValue = React.useMemo<ComboboxContextValue>(\n () => ({\n size,\n highContrast,\n placeholder,\n searchPlaceholder,\n filter,\n shouldFilter,\n loop,\n disabled,\n open,\n setOpen,\n value,\n setValue,\n searchValue,\n setSearchValue,\n selectedLabel,\n registerItemLabel,\n handleSelect,\n }),\n [\n size,\n highContrast,\n placeholder,\n searchPlaceholder,\n filter,\n shouldFilter,\n loop,\n disabled,\n open,\n setOpen,\n value,\n setValue,\n searchValue,\n setSearchValue,\n selectedLabel,\n registerItemLabel,\n handleSelect,\n ],\n );\n\n return (\n <ComboboxContext.Provider value={contextValue}>\n <Popover.Root open={open} onOpenChange={setOpen} {...rootProps}>\n {children}\n </Popover.Root>\n </ComboboxContext.Provider>\n );\n};\nComboboxRoot.displayName = 'Combobox.Root';\n\ntype ComboboxTriggerElement = HTMLButtonElement;\ntype ComboboxTriggerOwnProps = GetPropDefTypes<typeof comboboxTriggerPropDefs>;\ntype NativeTriggerProps = Omit<React.ComponentPropsWithoutRef<'button'>, 'color'>;\ninterface ComboboxTriggerProps extends NativeTriggerProps, MarginProps, ComboboxTriggerOwnProps {}\n/**\n * Trigger behaves like a styled button that opens the Popover,\n * syncing size/highContrast from Root while exposing select-like states.\n */\nconst ComboboxTrigger = React.forwardRef<ComboboxTriggerElement, ComboboxTriggerProps>((props, forwardedRef) => {\n const context = useComboboxContext('Combobox.Trigger');\n const { children, className, placeholder, disabled, readOnly, error, loading, color, radius, ...triggerProps } = extractProps(\n { size: context.size, highContrast: context.highContrast, ...props },\n { size: comboboxRootPropDefs.size, highContrast: comboboxRootPropDefs.highContrast },\n comboboxTriggerPropDefs,\n marginPropDefs,\n );\n\n // Extract material and panelBackground separately since they need to be passed as data attributes\n const { material, panelBackground } = props;\n\n const isDisabled = disabled ?? context.disabled;\n const ariaProps = React.useMemo(\n () => ({\n 'aria-expanded': context.open,\n 'aria-disabled': isDisabled || undefined,\n 'aria-haspopup': 'listbox' as const,\n }),\n [context.open, isDisabled],\n );\n\n const defaultContent = (\n <>\n <span className=\"rt-SelectTriggerInner\">\n <ComboboxValue placeholder={placeholder ?? context.placeholder} />\n </span>\n {loading ? (\n <div className=\"rt-SelectIcon rt-SelectLoadingIcon\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" strokeWidth=\"1\" strokeLinecap=\"round\" strokeDasharray=\"6 34\" strokeDashoffset=\"0\" className=\"rt-SelectLoadingSpinner\" />\n </svg>\n </div>\n ) : (\n <ChevronDownIcon className=\"rt-SelectIcon\" />\n )}\n </>\n );\n\n const { type: buttonType, ...restTriggerProps } = triggerProps;\n const resolvedButtonType = buttonType ?? 'button';\n\n const triggerChild = (\n <button\n data-accent-color={color}\n data-radius={radius}\n data-panel-background={panelBackground}\n data-material={material}\n data-error={error}\n data-loading={loading}\n data-disabled={isDisabled || undefined}\n data-read-only={readOnly || undefined}\n {...restTriggerProps}\n {...ariaProps}\n type={resolvedButtonType}\n disabled={isDisabled}\n ref={forwardedRef}\n className={classNames('rt-reset', 'rt-SelectTrigger', 'rt-ComboboxTrigger', className)}\n >\n {children ? requireReactElement(children) : defaultContent}\n </button>\n );\n\n return <Popover.Trigger disabled={isDisabled}>{triggerChild}</Popover.Trigger>;\n});\nComboboxTrigger.displayName = 'Combobox.Trigger';\n\ntype ComboboxValueElement = HTMLSpanElement;\ninterface ComboboxValueProps extends React.ComponentPropsWithoutRef<'span'> {\n placeholder?: string;\n}\n/**\n * Value mirrors Select.Value by showing the selected item's label\n * or falling back to placeholder text supplied by the consumer or context.\n */\nconst ComboboxValue = React.forwardRef<ComboboxValueElement, ComboboxValueProps>(({ placeholder, children, className, ...valueProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Value');\n const displayValue = context.selectedLabel ?? context.value ?? undefined;\n const fallback = placeholder ?? context.placeholder;\n return (\n <span {...valueProps} ref={forwardedRef} className={classNames('rt-ComboboxValue', className)}>\n {displayValue ?? children ?? fallback}\n </span>\n );\n});\nComboboxValue.displayName = 'Combobox.Value';\n\ntype ComboboxContentElement = React.ElementRef<typeof Popover.Content>;\ntype ComboboxContentOwnProps = GetPropDefTypes<typeof comboboxContentPropDefs> & {\n container?: React.ComponentPropsWithoutRef<typeof Popover.Content>['container'];\n};\ninterface ComboboxContentProps extends Omit<ComponentPropsWithout<typeof Popover.Content, RemovedProps>, 'size'>, ComboboxContentOwnProps {}\n/**\n * Content renders the dropdown surface, syncing tokens from the current Theme\n * and instantiating cmdk's Command list for roving focus + filtering.\n */\nconst ComboboxContent = React.forwardRef<ComboboxContentElement, ComboboxContentProps>((props, forwardedRef) => {\n const context = useComboboxContext('Combobox.Content');\n const themeContext = useThemeContext();\n const effectiveMaterial = themeContext.panelBackground;\n\n const sizeProp = props.size ?? context.size ?? comboboxContentPropDefs.size.default;\n const variantProp = props.variant ?? comboboxContentPropDefs.variant.default;\n const highContrastProp = props.highContrast ?? context.highContrast ?? comboboxContentPropDefs.highContrast.default;\n\n const { className, children, color, forceMount, container, ...contentProps } = extractProps(\n { ...props, size: sizeProp, variant: variantProp, highContrast: highContrastProp },\n comboboxContentPropDefs,\n );\n const resolvedColor = color || themeContext.accentColor;\n let sanitizedClassName = className;\n if (typeof sizeProp === 'string') {\n sanitizedClassName =\n className\n ?.split(/\\s+/)\n .filter(Boolean)\n .filter((token) => !/^rt-r-size-\\d$/.test(token))\n .join(' ') || undefined;\n }\n\n return (\n <Popover.Content\n size={sizeProp}\n data-accent-color={resolvedColor}\n data-material={effectiveMaterial}\n data-panel-background={effectiveMaterial}\n align=\"start\"\n sideOffset={4}\n collisionPadding={10}\n {...contentProps}\n forceMount={forceMount}\n container={container}\n ref={forwardedRef}\n className={classNames('rt-PopperContent', 'rt-BaseMenuContent', 'rt-ComboboxContent', sanitizedClassName)}\n >\n <Theme asChild>\n <ComboboxContentContext.Provider value={{ variant: variantProp, size: String(sizeProp), color: resolvedColor, material: effectiveMaterial, highContrast: highContrastProp }}>\n <CommandPrimitive\n loop={context.loop}\n value={context.searchValue}\n onValueChange={context.setSearchValue}\n shouldFilter={context.shouldFilter}\n filter={context.filter}\n className=\"rt-ComboboxCommand\"\n >\n {children}\n </CommandPrimitive>\n </ComboboxContentContext.Provider>\n </Theme>\n </Popover.Content>\n );\n});\nComboboxContent.displayName = 'Combobox.Content';\n\ntype ComboboxInputElement = React.ElementRef<typeof CommandPrimitive.Input>;\ninterface ComboboxInputProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> {\n startAdornment?: React.ReactNode;\n endAdornment?: React.ReactNode;\n variant?: TextFieldVariant;\n}\n/**\n * Input composes TextField tokens with cmdk's Command.Input to provide\n * automatic focus management and optional adornments.\n */\nconst ComboboxInput = React.forwardRef<ComboboxInputElement, ComboboxInputProps>(({ className, startAdornment, endAdornment, placeholder, variant: inputVariant, ...inputProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Input');\n const contentContext = useComboboxContentContext();\n const contentVariant = contentContext?.variant ?? 'solid';\n const color = contentContext?.color;\n const material = contentContext?.material;\n\n // Map combobox variant to textfield variant: solid -> surface, soft -> soft unless overridden\n const textFieldVariant = inputVariant ?? (contentVariant === 'solid' ? 'surface' : 'soft');\n\n const inputField = (\n <div\n className={classNames('rt-TextFieldRoot', 'rt-ComboboxInputRoot', `rt-r-size-${context.size}`, `rt-variant-${textFieldVariant}`)}\n data-accent-color={color}\n data-material={material}\n data-panel-background={material}\n >\n {startAdornment ? <div className=\"rt-TextFieldSlot\">{startAdornment}</div> : null}\n <CommandPrimitive.Input {...inputProps} ref={forwardedRef} placeholder={placeholder ?? context.searchPlaceholder} className={classNames('rt-reset', 'rt-TextFieldInput', className)} />\n {endAdornment ? (\n <div className=\"rt-TextFieldSlot\" data-side=\"right\">\n {endAdornment}\n </div>\n ) : null}\n </div>\n );\n\n if (contentContext) {\n return <div className=\"rt-ComboboxSearch\">{inputField}</div>;\n }\n\n return inputField;\n});\nComboboxInput.displayName = 'Combobox.Input';\n\ntype ComboboxListElement = React.ElementRef<typeof CommandPrimitive.List>;\ninterface ComboboxListProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.List> {}\n/**\n * List wraps cmdk's Command.List to inherit base menu styles and provides ScrollArea for the items.\n */\nconst ComboboxList = React.forwardRef<ComboboxListElement, ComboboxListProps>(({ className, ...listProps }, forwardedRef) => (\n <ScrollArea type=\"auto\" className=\"rt-ComboboxScrollArea\" scrollbars=\"vertical\" size=\"1\">\n <div className={classNames('rt-BaseMenuViewport', 'rt-ComboboxViewport')}>\n <CommandPrimitive.List {...listProps} ref={forwardedRef} className={classNames('rt-ComboboxList', className)} />\n </div>\n </ScrollArea>\n));\nComboboxList.displayName = 'Combobox.List';\n\ntype ComboboxEmptyElement = React.ElementRef<typeof CommandPrimitive.Empty>;\ninterface ComboboxEmptyProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> {}\n/**\n * Empty renders when no options match the search query.\n */\nconst ComboboxEmpty = React.forwardRef<ComboboxEmptyElement, ComboboxEmptyProps>(({ className, ...emptyProps }, forwardedRef) => (\n <CommandPrimitive.Empty {...emptyProps} ref={forwardedRef} className={classNames('rt-ComboboxEmpty', className)} />\n));\nComboboxEmpty.displayName = 'Combobox.Empty';\n\ntype ComboboxGroupElement = React.ElementRef<typeof CommandPrimitive.Group>;\ninterface ComboboxGroupProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group> {}\n/**\n * Group and Label mirror menu semantics for subheadings inside the list.\n */\nconst ComboboxGroup = React.forwardRef<ComboboxGroupElement, ComboboxGroupProps>(({ className, ...groupProps }, forwardedRef) => (\n <CommandPrimitive.Group {...groupProps} ref={forwardedRef} className={classNames('rt-BaseMenuGroup', 'rt-ComboboxGroup', className)} />\n));\nComboboxGroup.displayName = 'Combobox.Group';\n\ntype ComboboxLabelElement = React.ElementRef<'div'>;\ninterface ComboboxLabelProps extends React.ComponentPropsWithoutRef<'div'> {}\nconst ComboboxLabel = React.forwardRef<ComboboxLabelElement, ComboboxLabelProps>(({ className, ...labelProps }, forwardedRef) => (\n <div {...labelProps} ref={forwardedRef} className={classNames('rt-BaseMenuLabel', 'rt-ComboboxLabel', className)} />\n));\nComboboxLabel.displayName = 'Combobox.Label';\n\ntype ComboboxSeparatorElement = React.ElementRef<typeof CommandPrimitive.Separator>;\ninterface ComboboxSeparatorProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> {}\n/**\n * Separator visually divides logical sections of the option list.\n */\nconst ComboboxSeparator = React.forwardRef<ComboboxSeparatorElement, ComboboxSeparatorProps>(({ className, ...separatorProps }, forwardedRef) => (\n <CommandPrimitive.Separator {...separatorProps} ref={forwardedRef} className={classNames('rt-BaseMenuSeparator', 'rt-ComboboxSeparator', className)} />\n));\nComboboxSeparator.displayName = 'Combobox.Separator';\n\ntype ComboboxItemElement = React.ElementRef<typeof CommandPrimitive.Item>;\ninterface ComboboxItemProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item> {\n label?: string;\n}\n/**\n * Item wires cmdk's selection handling with Kookie UI tokens and\n * ensures labels are registered for displaying the current value.\n */\nconst ComboboxItem = React.forwardRef<ComboboxItemElement, ComboboxItemProps>(({ className, children, label, value, disabled, onSelect, ...itemProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Item');\n const contentContext = useComboboxContentContext();\n const itemLabel = label ?? (typeof children === 'string' ? children : String(value));\n const isSelected = value != null && context.value === value;\n const sizeClass = contentContext?.size ? `rt-r-size-${contentContext.size}` : undefined;\n\n React.useEffect(() => {\n if (value) {\n context.registerItemLabel(value, itemLabel);\n }\n }, [context, value, itemLabel]);\n\n const handleSelect = React.useCallback(\n (selectedValue: string) => {\n context.handleSelect(selectedValue);\n onSelect?.(selectedValue);\n },\n [context, onSelect],\n );\n\n const isDisabled = disabled ?? context.disabled ?? false;\n\n // Internal ref to clean up data-disabled attribute\n const internalRef = React.useRef<ComboboxItemElement | null>(null);\n\n // Ref callback to handle both forwarded ref and internal ref\n const itemRef = React.useCallback(\n (node: ComboboxItemElement | null) => {\n internalRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n (forwardedRef as React.MutableRefObject<ComboboxItemElement | null>).current = node;\n }\n },\n [forwardedRef],\n );\n\n // Remove data-disabled attribute if cmdk sets it incorrectly\n React.useEffect(() => {\n if (!isDisabled && internalRef.current) {\n const node = internalRef.current;\n // Check and remove immediately\n if (node.getAttribute('data-disabled') === 'false' || node.getAttribute('data-disabled') === '') {\n node.removeAttribute('data-disabled');\n }\n // Also watch for changes\n const observer = new MutationObserver(() => {\n if (node.getAttribute('data-disabled') === 'false' || node.getAttribute('data-disabled') === '') {\n node.removeAttribute('data-disabled');\n }\n });\n observer.observe(node, { attributes: true, attributeFilter: ['data-disabled'] });\n return () => observer.disconnect();\n }\n }, [isDisabled]);\n\n return (\n <CommandPrimitive.Item\n {...itemProps}\n value={value}\n {...(isDisabled ? { disabled: true } : {})}\n ref={itemRef}\n onSelect={handleSelect}\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-ComboboxItem', className)}\n >\n {isSelected ? (\n <span className={classNames('rt-BaseMenuItemIndicator', 'rt-ComboboxItemIndicator', sizeClass)}>\n <ThickCheckIcon className={classNames('rt-BaseMenuItemIndicatorIcon', 'rt-ComboboxItemIndicatorIcon', sizeClass)} />\n </span>\n ) : null}\n <Slottable>{children}</Slottable>\n </CommandPrimitive.Item>\n );\n});\nComboboxItem.displayName = 'Combobox.Item';\n\nexport {\n ComboboxRoot as Root,\n ComboboxTrigger as Trigger,\n ComboboxValue as Value,\n ComboboxContent as Content,\n ComboboxInput as Input,\n ComboboxList as List,\n ComboboxEmpty as Empty,\n ComboboxGroup as Group,\n ComboboxLabel as Label,\n ComboboxSeparator as Separator,\n ComboboxItem as Item,\n};\nexport type {\n ComboboxRootProps as RootProps,\n ComboboxTriggerProps as TriggerProps,\n ComboboxContentProps as ContentProps,\n ComboboxInputProps as InputProps,\n ComboboxListProps as ListProps,\n ComboboxEmptyProps as EmptyProps,\n ComboboxGroupProps as GroupProps,\n ComboboxLabelProps as LabelProps,\n ComboboxSeparatorProps as SeparatorProps,\n ComboboxItemProps as ItemProps,\n};\n"],
|
|
5
|
-
"mappings": "aASA,UAAYA,MAAW,QACvB,OAAOC,MAAgB,aACvB,OAAS,wBAAAC,MAA4B,oBACrC,OAAS,WAAWC,MAAwB,OAE5C,OAAS,gBAAAC,MAAoB,8BAC7B,OAAS,wBAAAC,EAAsB,2BAAAC,GAAyB,2BAAAC,MAA+B,sBACvF,OAAS,kBAAAC,OAAsB,2BAC/B,OAAS,mBAAAC,GAAiB,kBAAAC,OAAsB,aAChD,OAAS,SAAAC,GAAO,mBAAAC,OAAuB,aACvC,OAAS,uBAAAC,OAA2B,sCACpC,UAAYC,MAAa,eACzB,OAAS,cAAAC,OAAkB,mBAC3B,OAAS,aAAAC,OAAiB,YAC1B,MAAsC,
|
|
6
|
-
"names": ["React", "classNames", "useControllableState", "CommandPrimitive", "extractProps", "comboboxRootPropDefs", "comboboxTriggerPropDefs", "comboboxContentPropDefs", "marginPropDefs", "ChevronDownIcon", "ThickCheckIcon", "Theme", "useThemeContext", "requireReactElement", "Popover", "ScrollArea", "Slottable", "ComboboxContext", "useComboboxContext", "caller", "ctx", "ComboboxContentContext", "useComboboxContentContext", "ComboboxRoot", "props", "children", "size", "highContrast", "valueProp", "defaultValue", "onValueChange", "openProp", "defaultOpen", "onOpenChange", "placeholder", "searchPlaceholder", "searchValueProp", "defaultSearchValue", "onSearchValueChange", "filter", "shouldFilter", "loop", "disabled", "rootProps", "open", "setOpen", "value", "setValue", "searchValue", "setSearchValue", "labelMapRef", "registerItemLabel", "itemValue", "label", "
|
|
4
|
+
"sourcesContent": ["'use client';\n\n/**\n * Combobox is a compound component built on top of Popover and cmdk's Command list.\n * It mirrors the Select API while adding search-first behaviors including filtering,\n * async-friendly state management, and design token support for trigger, content,\n * and input variants.\n */\n\nimport * as React from 'react';\nimport classNames from 'classnames';\nimport { useControllableState } from 'radix-ui/internal';\nimport { Command as CommandPrimitive } from 'cmdk';\n\nimport { extractProps } from '../helpers/extract-props.js';\nimport { comboboxRootPropDefs, comboboxTriggerPropDefs, comboboxContentPropDefs } from './combobox.props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { ChevronDownIcon, ThickCheckIcon } from './icons.js';\nimport { Theme, useThemeContext } from './theme.js';\nimport { requireReactElement } from '../helpers/require-react-element.js';\nimport * as Popover from './popover.js';\nimport { ScrollArea } from './scroll-area.js';\nimport { Slottable } from './slot.js';\nimport { textFieldRootPropDefs } from './text-field.props.js';\n\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype TextFieldVariant = (typeof textFieldRootPropDefs.variant.values)[number];\ntype ComboboxValue = string | null;\n/**\n * Custom filter function for Combobox search.\n * @param value - The item's value being tested\n * @param search - The current search string\n * @param keywords - Optional keywords associated with the item\n * @returns A number between 0 and 1 where 0 means no match and 1 means exact match.\n * Fractional values indicate relevance for sorting.\n */\ntype CommandFilter = (value: string, search: string, keywords?: string[]) => number;\n\n/**\n * Additional props supported by Combobox.Root beyond the Radix Popover surface.\n */\ntype ComboboxRootOwnProps = GetPropDefTypes<typeof comboboxRootPropDefs> & {\n value?: ComboboxValue;\n defaultValue?: ComboboxValue;\n onValueChange?: (value: ComboboxValue) => void;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n placeholder?: string;\n searchPlaceholder?: string;\n searchValue?: string;\n defaultSearchValue?: string;\n onSearchValueChange?: (value: string) => void;\n filter?: CommandFilter;\n shouldFilter?: boolean;\n loop?: boolean;\n disabled?: boolean;\n /**\n * Whether to reset the search value when an option is selected.\n * @default true\n */\n resetSearchOnSelect?: boolean;\n /**\n * Accent color for the combobox trigger and content.\n */\n color?: (typeof comboboxTriggerPropDefs.color.values)[number];\n /**\n * Display value shown in the trigger. This is the recommended approach for\n * best performance as it avoids needing to mount items to register labels.\n * \n * Can be either:\n * - A string: Static display value\n * - A function: `(value: string | null) => string | undefined` - Called with current value\n * \n * Use this when:\n * - You have the selected item's label available (e.g., from your data source)\n * - Items haven't mounted yet (e.g., on initial render with a defaultValue)\n * - You want optimal performance with forceMount={false} (default)\n * \n * @example\n * // Static string\n * <Combobox.Root value=\"usa\" displayValue=\"United States\">\n * \n * // Function (recommended for dynamic data)\n * <Combobox.Root \n * value={selectedCountry}\n * displayValue={(value) => countries.find(c => c.code === value)?.name}\n * >\n * \n * If not provided, falls back to the label registered by the selected item\n * (requires forceMount={true}), then to the raw value.\n */\n displayValue?: string | ((value: ComboboxValue) => string | undefined);\n};\n\n/**\n * Internal context shared by all sub-components to avoid prop drilling.\n */\ninterface ComboboxContextValue extends ComboboxRootOwnProps {\n open: boolean;\n setOpen: (open: boolean) => void;\n value: ComboboxValue;\n setValue: (value: ComboboxValue) => void;\n searchValue: string;\n setSearchValue: (value: string) => void;\n /** Label registered by the selected item */\n selectedLabel?: string;\n /** Resolved display value (already computed from string or function) */\n resolvedDisplayValue?: string;\n registerItemLabel: (value: string, label: string) => void;\n unregisterItemLabel: (value: string) => void;\n handleSelect: (value: string) => void;\n listboxId: string;\n activeDescendantId: string | undefined;\n setActiveDescendantId: (id: string | undefined) => void;\n}\n\nconst ComboboxContext = React.createContext<ComboboxContextValue | null>(null);\n\n/**\n * Utility hook that ensures consumers are wrapped in Combobox.Root.\n */\nconst useComboboxContext = (caller: string) => {\n const ctx = React.useContext(ComboboxContext);\n if (!ctx) {\n throw new Error(`${caller} must be used within Combobox.Root`);\n }\n return ctx;\n};\n\n/**\n * Context for values that are only available inside Content (e.g., variant, color)\n * so that Input/Item can style themselves consistently.\n */\nconst ComboboxContentContext = React.createContext<{ variant: 'solid' | 'soft'; size?: string; color?: string; material?: string; highContrast?: boolean } | null>(null);\nconst useComboboxContentContext = () => {\n const ctx = React.useContext(ComboboxContentContext);\n return ctx; // Optional - Input might not always be in Content\n};\n\ntype PopoverRootProps = React.ComponentPropsWithoutRef<typeof Popover.Root>;\ninterface ComboboxRootProps extends PopoverRootProps, ComboboxRootOwnProps {}\n/**\n * Root component that wires up Popover behavior, controllable state,\n * and shared context for trigger/content/input sub-components.\n */\nconst ComboboxRoot: React.FC<ComboboxRootProps> = (props) => {\n const {\n children,\n size = comboboxRootPropDefs.size.default,\n highContrast = comboboxRootPropDefs.highContrast.default,\n value: valueProp,\n defaultValue = null,\n onValueChange,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n placeholder = 'Select an option',\n searchPlaceholder = 'Search options...',\n searchValue: searchValueProp,\n defaultSearchValue = '',\n onSearchValueChange,\n filter,\n shouldFilter = true,\n loop = true,\n disabled,\n resetSearchOnSelect = true,\n color,\n displayValue: displayValueProp,\n ...rootProps\n } = props;\n\n // Generate stable IDs for accessibility\n const generatedId = React.useId();\n const listboxId = `combobox-listbox-${generatedId}`;\n const [activeDescendantId, setActiveDescendantId] = React.useState<string | undefined>(undefined);\n\n const [open, setOpen] = useControllableState({\n prop: openProp,\n defaultProp: defaultOpen,\n onChange: onOpenChange,\n });\n\n const [value, setValue] = useControllableState<ComboboxValue>({\n prop: valueProp,\n defaultProp: defaultValue,\n onChange: onValueChange,\n });\n\n const [searchValue, setSearchValue] = useControllableState<string>({\n prop: searchValueProp,\n defaultProp: defaultSearchValue,\n onChange: onSearchValueChange,\n });\n\n const labelMapRef = React.useRef(new Map<string, string>());\n // Track the selected label in state so it triggers re-renders when items register\n const [selectedLabel, setSelectedLabel] = React.useState<string | undefined>(undefined);\n\n const registerItemLabel = React.useCallback((itemValue: string, label: string) => {\n labelMapRef.current.set(itemValue, label);\n // If this item matches the current value, update the selected label\n if (itemValue === value) {\n setSelectedLabel(label);\n }\n }, [value]);\n\n const unregisterItemLabel = React.useCallback((itemValue: string) => {\n labelMapRef.current.delete(itemValue);\n }, []);\n\n // Update selected label when value changes\n React.useEffect(() => {\n if (value != null) {\n const label = labelMapRef.current.get(value);\n setSelectedLabel(label);\n } else {\n setSelectedLabel(undefined);\n }\n }, [value]);\n\n const handleSelect = React.useCallback(\n (nextValue: string) => {\n setValue(nextValue);\n setOpen(false);\n if (resetSearchOnSelect) {\n setSearchValue('');\n }\n },\n [setOpen, setSearchValue, setValue, resetSearchOnSelect],\n );\n\n // Development mode warning for value not matching any registered item\n React.useEffect(() => {\n if (process.env.NODE_ENV !== 'production' && value != null && !labelMapRef.current.has(value)) {\n // Defer the check to allow items to register first\n const timeoutId = setTimeout(() => {\n if (value != null && !labelMapRef.current.has(value)) {\n console.warn(\n `[Combobox] The value \"${value}\" does not match any Combobox.Item. ` +\n `Make sure each Item has a matching value prop.`,\n );\n }\n }, 0);\n return () => clearTimeout(timeoutId);\n }\n }, [value]);\n\n // Resolve displayValue: compute if function, use directly if string\n const resolvedDisplayValue = React.useMemo(() => {\n if (displayValueProp == null) return undefined;\n if (typeof displayValueProp === 'function') {\n return displayValueProp(value);\n }\n return displayValueProp;\n }, [displayValueProp, value]);\n\n const contextValue = React.useMemo<ComboboxContextValue>(\n () => ({\n size,\n highContrast,\n placeholder,\n searchPlaceholder,\n filter,\n shouldFilter,\n loop,\n disabled,\n resetSearchOnSelect,\n color,\n resolvedDisplayValue,\n open,\n setOpen,\n value,\n setValue,\n searchValue,\n setSearchValue,\n selectedLabel,\n registerItemLabel,\n unregisterItemLabel,\n handleSelect,\n listboxId,\n activeDescendantId,\n setActiveDescendantId,\n }),\n [\n size,\n highContrast,\n placeholder,\n searchPlaceholder,\n filter,\n shouldFilter,\n loop,\n disabled,\n resetSearchOnSelect,\n color,\n resolvedDisplayValue,\n open,\n setOpen,\n value,\n setValue,\n searchValue,\n setSearchValue,\n selectedLabel,\n registerItemLabel,\n unregisterItemLabel,\n handleSelect,\n listboxId,\n activeDescendantId,\n setActiveDescendantId,\n ],\n );\n\n return (\n <ComboboxContext.Provider value={contextValue}>\n <Popover.Root open={open} onOpenChange={setOpen} {...rootProps}>\n {children}\n </Popover.Root>\n </ComboboxContext.Provider>\n );\n};\nComboboxRoot.displayName = 'Combobox.Root';\n\ntype ComboboxTriggerElement = HTMLButtonElement;\ntype ComboboxTriggerOwnProps = GetPropDefTypes<typeof comboboxTriggerPropDefs>;\ntype NativeTriggerProps = Omit<React.ComponentPropsWithoutRef<'button'>, 'color'>;\ninterface ComboboxTriggerProps extends NativeTriggerProps, MarginProps, ComboboxTriggerOwnProps {}\n/**\n * Trigger behaves like a styled button that opens the Popover,\n * syncing size/highContrast from Root while exposing select-like states.\n */\nconst ComboboxTrigger = React.forwardRef<ComboboxTriggerElement, ComboboxTriggerProps>((props, forwardedRef) => {\n const context = useComboboxContext('Combobox.Trigger');\n const { children, className, placeholder, disabled, readOnly, error, loading, color, radius, ...triggerProps } = extractProps(\n { size: context.size, highContrast: context.highContrast, ...props },\n { size: comboboxRootPropDefs.size, highContrast: comboboxRootPropDefs.highContrast },\n comboboxTriggerPropDefs,\n marginPropDefs,\n );\n\n // Extract material and panelBackground separately since they need to be passed as data attributes\n const { material, panelBackground } = props;\n\n const isDisabled = disabled ?? context.disabled;\n\n // Use color from props or fall back to context color\n const resolvedColor = color ?? context.color;\n\n // Comprehensive ARIA attributes for combobox pattern (WAI-ARIA 1.2)\n const ariaProps = React.useMemo(\n () => ({\n role: 'combobox' as const,\n 'aria-expanded': context.open,\n 'aria-disabled': isDisabled || undefined,\n 'aria-haspopup': 'listbox' as const,\n 'aria-controls': context.open ? context.listboxId : undefined,\n 'aria-activedescendant': context.open ? context.activeDescendantId : undefined,\n 'aria-autocomplete': 'list' as const,\n }),\n [context.open, context.listboxId, context.activeDescendantId, isDisabled],\n );\n\n const defaultContent = (\n <>\n <span className=\"rt-SelectTriggerInner\">\n <ComboboxValue placeholder={placeholder ?? context.placeholder} />\n </span>\n {loading ? (\n <div className=\"rt-SelectIcon rt-SelectLoadingIcon\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" strokeWidth=\"1\" strokeLinecap=\"round\" strokeDasharray=\"6 34\" strokeDashoffset=\"0\" className=\"rt-SelectLoadingSpinner\" />\n </svg>\n </div>\n ) : (\n <ChevronDownIcon className=\"rt-SelectIcon\" />\n )}\n </>\n );\n\n const { type: buttonType, ...restTriggerProps } = triggerProps;\n const resolvedButtonType = buttonType ?? 'button';\n\n const triggerChild = (\n <button\n data-accent-color={resolvedColor}\n data-radius={radius}\n data-panel-background={panelBackground}\n data-material={material}\n data-error={error}\n data-loading={loading}\n data-disabled={isDisabled || undefined}\n data-read-only={readOnly || undefined}\n {...restTriggerProps}\n {...ariaProps}\n type={resolvedButtonType}\n disabled={isDisabled}\n ref={forwardedRef}\n className={classNames('rt-reset', 'rt-SelectTrigger', 'rt-ComboboxTrigger', className)}\n >\n {children ? requireReactElement(children) : defaultContent}\n </button>\n );\n\n return <Popover.Trigger disabled={isDisabled}>{triggerChild}</Popover.Trigger>;\n});\nComboboxTrigger.displayName = 'Combobox.Trigger';\n\ntype ComboboxValueElement = HTMLSpanElement;\ninterface ComboboxValueProps extends React.ComponentPropsWithoutRef<'span'> {\n placeholder?: string;\n}\n/**\n * Value mirrors Select.Value by showing the selected item's label\n * or falling back to placeholder text supplied by the consumer or context.\n * \n * Priority: resolvedDisplayValue (explicit) > selectedLabel (from items) > raw value > children > placeholder\n */\nconst ComboboxValue = React.forwardRef<ComboboxValueElement, ComboboxValueProps>(({ placeholder, children, className, ...valueProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Value');\n // Priority: explicit displayValue (resolved) > registered label > raw value\n const displayValue = context.resolvedDisplayValue ?? context.selectedLabel ?? context.value ?? undefined;\n const fallback = placeholder ?? context.placeholder;\n return (\n <span {...valueProps} ref={forwardedRef} className={classNames('rt-ComboboxValue', className)}>\n {displayValue ?? children ?? fallback}\n </span>\n );\n});\nComboboxValue.displayName = 'Combobox.Value';\n\ntype ComboboxContentElement = React.ElementRef<typeof Popover.Content>;\ntype ComboboxContentOwnProps = GetPropDefTypes<typeof comboboxContentPropDefs> & {\n container?: React.ComponentPropsWithoutRef<typeof Popover.Content>['container'];\n};\ninterface ComboboxContentProps extends Omit<ComponentPropsWithout<typeof Popover.Content, RemovedProps>, 'size'>, ComboboxContentOwnProps {}\n/**\n * Content renders the dropdown surface, syncing tokens from the current Theme\n * and instantiating cmdk's Command list for roving focus + filtering.\n */\nconst ComboboxContent = React.forwardRef<ComboboxContentElement, ComboboxContentProps>((props, forwardedRef) => {\n const context = useComboboxContext('Combobox.Content');\n const themeContext = useThemeContext();\n const effectiveMaterial = themeContext.panelBackground;\n\n const sizeProp = props.size ?? context.size ?? comboboxContentPropDefs.size.default;\n const variantProp = props.variant ?? comboboxContentPropDefs.variant.default;\n const highContrastProp = props.highContrast ?? context.highContrast ?? comboboxContentPropDefs.highContrast.default;\n\n const { className, children, color, forceMount, container, ...contentProps } = extractProps(\n { ...props, size: sizeProp, variant: variantProp, highContrast: highContrastProp },\n comboboxContentPropDefs,\n );\n const resolvedColor = color || context.color || themeContext.accentColor;\n \n // Memoize className sanitization to avoid string operations on every render\n const sanitizedClassName = React.useMemo(() => {\n if (typeof sizeProp !== 'string') return className;\n return className\n ?.split(/\\s+/)\n .filter(Boolean)\n .filter((token) => !/^rt-r-size-\\d$/.test(token))\n .join(' ') || undefined;\n }, [className, sizeProp]);\n\n /**\n * forceMount behavior:\n * - When true: Content stays mounted when closed, allowing items to register labels\n * for display in the trigger. Use this if you need dynamic label resolution.\n * - When false/undefined (default): Content unmounts when closed for better performance.\n * Use the `displayValue` prop on Root to show the selected label instead.\n * \n * For best performance with large lists, keep forceMount=undefined and provide displayValue.\n */\n const shouldForceMount = forceMount === true ? true : undefined;\n\n return (\n <Popover.Content\n size={sizeProp}\n data-accent-color={resolvedColor}\n data-material={effectiveMaterial}\n data-panel-background={effectiveMaterial}\n align=\"start\"\n sideOffset={4}\n collisionPadding={10}\n {...contentProps}\n forceMount={shouldForceMount}\n container={container}\n ref={forwardedRef}\n className={classNames('rt-PopperContent', 'rt-BaseMenuContent', 'rt-ComboboxContent', sanitizedClassName)}\n >\n <Theme asChild>\n <ComboboxContentContext.Provider value={{ variant: variantProp, size: String(sizeProp), color: resolvedColor, material: effectiveMaterial, highContrast: highContrastProp }}>\n <CommandPrimitive\n loop={context.loop}\n shouldFilter={context.shouldFilter}\n filter={context.filter}\n className=\"rt-ComboboxCommand\"\n >\n {children}\n </CommandPrimitive>\n </ComboboxContentContext.Provider>\n </Theme>\n </Popover.Content>\n );\n});\nComboboxContent.displayName = 'Combobox.Content';\n\ntype ComboboxInputElement = React.ElementRef<typeof CommandPrimitive.Input>;\ninterface ComboboxInputProps extends Omit<React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>, 'value' | 'onValueChange'> {\n startAdornment?: React.ReactNode;\n endAdornment?: React.ReactNode;\n variant?: TextFieldVariant;\n /** Controlled search value. Falls back to Root's searchValue if not provided. */\n value?: string;\n /** Callback when search value changes. Falls back to Root's onSearchValueChange if not provided. */\n onValueChange?: (value: string) => void;\n}\n/**\n * Input composes TextField tokens with cmdk's Command.Input to provide\n * automatic focus management and optional adornments.\n */\nconst ComboboxInput = React.forwardRef<ComboboxInputElement, ComboboxInputProps>(({ className, startAdornment, endAdornment, placeholder, variant: inputVariant, value, onValueChange, ...inputProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Input');\n const contentContext = useComboboxContentContext();\n const contentVariant = contentContext?.variant ?? 'solid';\n const color = contentContext?.color;\n const material = contentContext?.material;\n\n /**\n * Map combobox content variant to TextField variant:\n * - Content 'solid' \u2192 Input 'surface' (elevated input on solid background)\n * - Content 'soft' \u2192 Input 'soft' (subtle input on soft background)\n * This ensures visual harmony between the input and surrounding content.\n */\n const textFieldVariant = inputVariant ?? (contentVariant === 'solid' ? 'surface' : 'soft');\n\n // Use controlled search value from context, allow override via props\n const searchValue = value ?? context.searchValue;\n const handleSearchChange = onValueChange ?? context.setSearchValue;\n\n const inputField = (\n <div\n className={classNames('rt-TextFieldRoot', 'rt-ComboboxInputRoot', `rt-r-size-${context.size}`, `rt-variant-${textFieldVariant}`)}\n data-accent-color={color}\n data-material={material}\n data-panel-background={material}\n >\n {startAdornment ? <div className=\"rt-TextFieldSlot\">{startAdornment}</div> : null}\n <CommandPrimitive.Input\n {...inputProps}\n ref={forwardedRef}\n value={searchValue}\n onValueChange={handleSearchChange}\n placeholder={placeholder ?? context.searchPlaceholder}\n className={classNames('rt-reset', 'rt-TextFieldInput', className)}\n />\n {endAdornment ? (\n <div className=\"rt-TextFieldSlot\" data-side=\"right\">\n {endAdornment}\n </div>\n ) : null}\n </div>\n );\n\n if (contentContext) {\n return <div className=\"rt-ComboboxSearch\">{inputField}</div>;\n }\n\n return inputField;\n});\nComboboxInput.displayName = 'Combobox.Input';\n\ntype ComboboxListElement = React.ElementRef<typeof CommandPrimitive.List>;\ninterface ComboboxListProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.List> {}\n/**\n * List wraps cmdk's Command.List to inherit base menu styles and provides ScrollArea for the items.\n * Also handles aria-activedescendant tracking via a single MutationObserver for all items.\n */\nconst ComboboxList = React.forwardRef<ComboboxListElement, ComboboxListProps>(({ className, ...listProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.List');\n const listRef = React.useRef<HTMLDivElement | null>(null);\n\n // Combined ref handling\n const combinedRef = React.useCallback(\n (node: HTMLDivElement | null) => {\n listRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n (forwardedRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [forwardedRef],\n );\n\n /**\n * Single MutationObserver at List level to track aria-activedescendant.\n * This replaces per-item observers for better performance with large lists.\n */\n React.useEffect(() => {\n const listNode = listRef.current;\n if (!listNode) return;\n\n const updateActiveDescendant = () => {\n const selectedItem = listNode.querySelector('[data-selected=\"true\"], [aria-selected=\"true\"]');\n const itemId = selectedItem?.id;\n context.setActiveDescendantId(itemId || undefined);\n };\n\n // Initial check\n updateActiveDescendant();\n\n // Watch for attribute changes on any descendant\n const observer = new MutationObserver(updateActiveDescendant);\n observer.observe(listNode, {\n attributes: true,\n attributeFilter: ['data-selected', 'aria-selected'],\n subtree: true,\n });\n\n return () => observer.disconnect();\n }, [context.setActiveDescendantId]);\n\n return (\n <ScrollArea type=\"auto\" className=\"rt-ComboboxScrollArea\" scrollbars=\"vertical\" size=\"1\">\n <div className={classNames('rt-BaseMenuViewport', 'rt-ComboboxViewport')}>\n <CommandPrimitive.List\n {...listProps}\n ref={combinedRef}\n id={context.listboxId}\n role=\"listbox\"\n aria-label=\"Options\"\n className={classNames('rt-ComboboxList', className)}\n />\n </div>\n </ScrollArea>\n );\n});\nComboboxList.displayName = 'Combobox.List';\n\ntype ComboboxEmptyElement = React.ElementRef<typeof CommandPrimitive.Empty>;\ninterface ComboboxEmptyProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> {}\n/**\n * Empty renders when no options match the search query.\n */\nconst ComboboxEmpty = React.forwardRef<ComboboxEmptyElement, ComboboxEmptyProps>(({ className, ...emptyProps }, forwardedRef) => (\n <CommandPrimitive.Empty {...emptyProps} ref={forwardedRef} className={classNames('rt-ComboboxEmpty', className)} />\n));\nComboboxEmpty.displayName = 'Combobox.Empty';\n\ntype ComboboxGroupElement = React.ElementRef<typeof CommandPrimitive.Group>;\ninterface ComboboxGroupProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group> {}\n/**\n * Group and Label mirror menu semantics for subheadings inside the list.\n */\nconst ComboboxGroup = React.forwardRef<ComboboxGroupElement, ComboboxGroupProps>(({ className, ...groupProps }, forwardedRef) => (\n <CommandPrimitive.Group {...groupProps} ref={forwardedRef} className={classNames('rt-BaseMenuGroup', 'rt-ComboboxGroup', className)} />\n));\nComboboxGroup.displayName = 'Combobox.Group';\n\ntype ComboboxLabelElement = React.ElementRef<'div'>;\ninterface ComboboxLabelProps extends React.ComponentPropsWithoutRef<'div'> {}\nconst ComboboxLabel = React.forwardRef<ComboboxLabelElement, ComboboxLabelProps>(({ className, ...labelProps }, forwardedRef) => (\n <div {...labelProps} ref={forwardedRef} className={classNames('rt-BaseMenuLabel', 'rt-ComboboxLabel', className)} />\n));\nComboboxLabel.displayName = 'Combobox.Label';\n\ntype ComboboxSeparatorElement = React.ElementRef<typeof CommandPrimitive.Separator>;\ninterface ComboboxSeparatorProps extends React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator> {}\n/**\n * Separator visually divides logical sections of the option list.\n */\nconst ComboboxSeparator = React.forwardRef<ComboboxSeparatorElement, ComboboxSeparatorProps>(({ className, ...separatorProps }, forwardedRef) => (\n <CommandPrimitive.Separator {...separatorProps} ref={forwardedRef} className={classNames('rt-BaseMenuSeparator', 'rt-ComboboxSeparator', className)} />\n));\nComboboxSeparator.displayName = 'Combobox.Separator';\n\ntype ComboboxItemElement = React.ElementRef<typeof CommandPrimitive.Item>;\ninterface ComboboxItemProps extends Omit<React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>, 'keywords'> {\n /** Display label for the item. Also used for search unless keywords are provided. */\n label?: string;\n /** Additional keywords for search filtering (overrides automatic label-based search). */\n keywords?: string[];\n}\n/**\n * Item wires cmdk's selection handling with Kookie UI tokens and\n * ensures labels are registered for displaying the current value.\n */\n/**\n * Extracts text content from React children recursively.\n * Used to derive searchable labels from JSX children.\n */\nfunction extractTextFromChildren(children: React.ReactNode): string {\n if (typeof children === 'string') return children;\n if (typeof children === 'number') return String(children);\n if (children == null || typeof children === 'boolean') return '';\n if (Array.isArray(children)) {\n return children.map(extractTextFromChildren).filter(Boolean).join(' ');\n }\n if (React.isValidElement(children)) {\n const props = children.props as { children?: React.ReactNode };\n if (props.children) {\n return extractTextFromChildren(props.children);\n }\n }\n return '';\n}\n\nconst ComboboxItem = React.forwardRef<ComboboxItemElement, ComboboxItemProps>(({ className, children, label, value, disabled, onSelect, keywords, ...itemProps }, forwardedRef) => {\n const context = useComboboxContext('Combobox.Item');\n const contentContext = useComboboxContentContext();\n \n // Memoize label extraction to avoid recursive traversal on every render\n const extractedLabel = React.useMemo(() => extractTextFromChildren(children), [children]);\n const itemLabel = label ?? (extractedLabel || String(value));\n const isSelected = value != null && context.value === value;\n const sizeClass = contentContext?.size ? `rt-r-size-${contentContext.size}` : undefined;\n\n // Use provided keywords, or default to the item label for search\n // This allows searching by display text even when value is different (e.g., \"usa\" vs \"United States\")\n const searchKeywords = keywords ?? [itemLabel];\n\n // Generate stable ID for this item for aria-activedescendant\n const generatedId = React.useId();\n const itemId = `combobox-item-${generatedId}`;\n\n // Destructure stable references to avoid effect re-runs when unrelated context values change\n const { registerItemLabel, unregisterItemLabel, handleSelect: contextHandleSelect } = context;\n\n // Register/unregister label for display in trigger\n React.useEffect(() => {\n if (value) {\n registerItemLabel(value, itemLabel);\n return () => unregisterItemLabel(value);\n }\n }, [registerItemLabel, unregisterItemLabel, value, itemLabel]);\n\n const handleSelect = React.useCallback(\n (selectedValue: string) => {\n contextHandleSelect(selectedValue);\n onSelect?.(selectedValue);\n },\n [contextHandleSelect, onSelect],\n );\n\n const isDisabled = disabled ?? context.disabled ?? false;\n\n /**\n * Performance notes:\n * - data-disabled workaround: Handled via CSS selectors in combobox.css\n * rather than per-item MutationObservers.\n * - aria-activedescendant: Tracked by a single observer in ComboboxList\n * rather than per-item observers.\n */\n\n return (\n <CommandPrimitive.Item\n {...itemProps}\n id={itemId}\n value={value}\n keywords={searchKeywords}\n role=\"option\"\n aria-selected={isSelected}\n {...(isDisabled ? { disabled: true, 'aria-disabled': true } : {})}\n ref={forwardedRef}\n onSelect={handleSelect}\n className={classNames('rt-reset', 'rt-BaseMenuItem', 'rt-ComboboxItem', className)}\n >\n {isSelected ? (\n <span className={classNames('rt-BaseMenuItemIndicator', 'rt-ComboboxItemIndicator', sizeClass)}>\n <ThickCheckIcon className={classNames('rt-BaseMenuItemIndicatorIcon', 'rt-ComboboxItemIndicatorIcon', sizeClass)} />\n </span>\n ) : null}\n <Slottable>{children}</Slottable>\n </CommandPrimitive.Item>\n );\n});\nComboboxItem.displayName = 'Combobox.Item';\n\nexport {\n ComboboxRoot as Root,\n ComboboxTrigger as Trigger,\n ComboboxValue as Value,\n ComboboxContent as Content,\n ComboboxInput as Input,\n ComboboxList as List,\n ComboboxEmpty as Empty,\n ComboboxGroup as Group,\n ComboboxLabel as Label,\n ComboboxSeparator as Separator,\n ComboboxItem as Item,\n};\nexport type {\n ComboboxRootProps as RootProps,\n ComboboxTriggerProps as TriggerProps,\n ComboboxValueProps as ValueProps,\n ComboboxContentProps as ContentProps,\n ComboboxInputProps as InputProps,\n ComboboxListProps as ListProps,\n ComboboxEmptyProps as EmptyProps,\n ComboboxGroupProps as GroupProps,\n ComboboxLabelProps as LabelProps,\n ComboboxSeparatorProps as SeparatorProps,\n ComboboxItemProps as ItemProps,\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "classNames", "useControllableState", "CommandPrimitive", "extractProps", "comboboxRootPropDefs", "comboboxTriggerPropDefs", "comboboxContentPropDefs", "marginPropDefs", "ChevronDownIcon", "ThickCheckIcon", "Theme", "useThemeContext", "requireReactElement", "Popover", "ScrollArea", "Slottable", "ComboboxContext", "useComboboxContext", "caller", "ctx", "ComboboxContentContext", "useComboboxContentContext", "ComboboxRoot", "props", "children", "size", "highContrast", "valueProp", "defaultValue", "onValueChange", "openProp", "defaultOpen", "onOpenChange", "placeholder", "searchPlaceholder", "searchValueProp", "defaultSearchValue", "onSearchValueChange", "filter", "shouldFilter", "loop", "disabled", "resetSearchOnSelect", "color", "displayValueProp", "rootProps", "listboxId", "activeDescendantId", "setActiveDescendantId", "open", "setOpen", "value", "setValue", "searchValue", "setSearchValue", "labelMapRef", "selectedLabel", "setSelectedLabel", "registerItemLabel", "itemValue", "label", "unregisterItemLabel", "handleSelect", "nextValue", "resolvedDisplayValue", "contextValue", "ComboboxTrigger", "forwardedRef", "context", "className", "readOnly", "error", "loading", "radius", "triggerProps", "material", "panelBackground", "isDisabled", "resolvedColor", "ariaProps", "defaultContent", "ComboboxValue", "buttonType", "restTriggerProps", "triggerChild", "valueProps", "displayValue", "fallback", "ComboboxContent", "themeContext", "effectiveMaterial", "sizeProp", "variantProp", "highContrastProp", "forceMount", "container", "contentProps", "sanitizedClassName", "token", "shouldForceMount", "ComboboxInput", "startAdornment", "endAdornment", "inputVariant", "inputProps", "contentContext", "contentVariant", "textFieldVariant", "handleSearchChange", "inputField", "ComboboxList", "listProps", "listRef", "combinedRef", "node", "listNode", "updateActiveDescendant", "itemId", "observer", "ComboboxEmpty", "emptyProps", "ComboboxGroup", "groupProps", "ComboboxLabel", "labelProps", "ComboboxSeparator", "separatorProps", "extractTextFromChildren", "ComboboxItem", "onSelect", "keywords", "itemProps", "extractedLabel", "itemLabel", "isSelected", "sizeClass", "searchKeywords", "contextHandleSelect", "selectedValue"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { textFieldRootPropDefs, textFieldSlotPropDefs } from './text-field.props.js';
|
|
2
|
+
import { textFieldRootPropDefs, textFieldSlotPropDefs, type TextFieldSlotScrubProps } from './text-field.props.js';
|
|
3
3
|
import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';
|
|
4
4
|
import type { NotInputTextualAttributes } from '../helpers/input-attributes.js';
|
|
5
5
|
import type { MarginProps } from '../props/margin.props.js';
|
|
@@ -13,7 +13,7 @@ type TextFieldInputProps = ComponentPropsWithout<'input', NotInputTextualAttribu
|
|
|
13
13
|
interface TextFieldRootProps extends TextFieldInputProps, MarginProps, TextFieldRootOwnProps {
|
|
14
14
|
}
|
|
15
15
|
declare const TextFieldRoot: React.ForwardRefExoticComponent<TextFieldRootProps & React.RefAttributes<HTMLInputElement>>;
|
|
16
|
-
type TextFieldSlotOwnProps = GetPropDefTypes<typeof textFieldSlotPropDefs
|
|
16
|
+
type TextFieldSlotOwnProps = GetPropDefTypes<typeof textFieldSlotPropDefs> & TextFieldSlotScrubProps;
|
|
17
17
|
interface TextFieldSlotProps extends ComponentPropsWithout<'div', RemovedProps>, TextFieldSlotOwnProps {
|
|
18
18
|
}
|
|
19
19
|
declare const TextFieldSlot: React.ForwardRefExoticComponent<TextFieldSlotProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-field.d.ts","sourceRoot":"","sources":["../../../src/components/text-field.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"text-field.d.ts","sourceRoot":"","sources":["../../../src/components/text-field.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,uBAAuB,EAC7B,MAAM,uBAAuB,CAAC;AAI/B,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,KAAK,qBAAqB,GAAG,eAAe,CAAC,OAAO,qBAAqB,CAAC,GAAG;IAC3E,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,IAAI,CAAC,EACD,MAAM,GACN,gBAAgB,GAChB,OAAO,GACP,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,MAAM,CAAC;CACZ,CAAC;AACF,KAAK,mBAAmB,GAAG,qBAAqB,CAC9C,OAAO,EACP,yBAAyB,GAAG,OAAO,GAAG,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CACjF,CAAC;AACF,UAAU,kBAAmB,SAAQ,mBAAmB,EAAE,WAAW,EAAE,qBAAqB;CAAG;AAC/F,QAAA,MAAM,aAAa,6FAkGlB,CAAC;AAIF,KAAK,qBAAqB,GAAG,eAAe,CAAC,OAAO,qBAAqB,CAAC,GAAG,uBAAuB,CAAC;AACrG,UAAU,kBACR,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,CAAC,EAChD,qBAAqB;CAAG;AAC5B,QAAA,MAAM,aAAa,2FAiOlB,CAAC;AAGF,OAAO,EAAE,aAAa,IAAI,IAAI,EAAE,aAAa,IAAI,IAAI,EAAE,CAAC;AACxD,YAAY,EAAE,kBAAkB,IAAI,SAAS,EAAE,kBAAkB,IAAI,SAAS,EAAE,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use client";import*as e from"react";import
|
|
1
|
+
"use client";import*as e from"react";import*as K from"react-dom";import X from"classnames";import{composeRefs as Y}from"radix-ui/internal";import{textFieldRootPropDefs as U,textFieldSlotPropDefs as J}from"./text-field.props.js";import{extractProps as q}from"../helpers/extract-props.js";import{marginPropDefs as Q}from"../props/margin.props.js";const G=e.forwardRef((I,L)=>{const c=e.useRef(null),{children:d,className:h,color:T,radius:g,panelBackground:F,material:M,style:R,...o}=q(I,U,Q),E=M||F,b=e.useId(),x=o.error||o.isInvalid,{"aria-describedby":y,"aria-labelledby":P}=o,p=e.useMemo(()=>{const l=[];return o.errorMessage&&l.push(b),y&&l.push(y),l.length>0?l.join(" "):void 0},[o.errorMessage,y,b]),m=e.useMemo(()=>({"aria-invalid":x,"aria-describedby":p,"aria-labelledby":P}),[x,p,P]),{error:A,errorMessage:k,isInvalid:N,required:f,"aria-describedby":u,"aria-labelledby":s,...v}=o,C=e.useCallback(l=>{const t=l.target;if(t.closest("input, button, a"))return;const n=c.current;if(!n)return;const r=t.closest(`
|
|
2
2
|
.rt-TextFieldSlot[data-side='right'],
|
|
3
3
|
.rt-TextFieldSlot:not([data-side='right']) ~ .rt-TextFieldSlot:not([data-side='left'])
|
|
4
|
-
`)?
|
|
4
|
+
`)?n.value.length:0;requestAnimationFrame(()=>{try{n.setSelectionRange(r,r)}catch{}n.focus()})},[]);return e.createElement("div",{"data-accent-color":T,"data-radius":g,"data-panel-background":E,"data-material":E,style:R,className:X("rt-TextFieldRoot",h,{"rt-error":x}),onPointerDown:C},e.createElement("input",{spellCheck:"false",...v,...m,ref:Y(c,L),className:"rt-reset rt-TextFieldInput"}),d,o.errorMessage&&e.createElement("div",{id:b,className:"rt-TextFieldErrorMessage",role:"alert","aria-live":"polite"},o.errorMessage))});G.displayName="TextField.Root";const _=e.forwardRef((I,L)=>{const{scrub:c,scrubValue:d,scrubStep:h=1,scrubSensitivity:T=1,scrubMin:g,scrubMax:F,scrubShiftMultiplier:M=10,scrubAltMultiplier:R=.1,onScrub:o,...E}=I,{className:b,color:x,side:y,...P}=q(E,J),p=e.useRef(null),[m,A]=e.useState(!1),[k,N]=e.useState({x:0,y:0}),f=e.useRef(0),u=e.useRef(0),s=e.useRef(0),v=e.useRef({scrubValue:d,scrubStep:h,scrubSensitivity:T,scrubMin:g,scrubMax:F,scrubShiftMultiplier:M,scrubAltMultiplier:R,onScrub:o});v.current={scrubValue:d,scrubStep:h,scrubSensitivity:T,scrubMin:g,scrubMax:F,scrubShiftMultiplier:M,scrubAltMultiplier:R,onScrub:o};const C=e.useCallback(t=>{if(!c||t.target.closest("input, button, a"))return;t.preventDefault(),f.current=0,u.current=d??0,s.current=t.clientX,N({x:t.clientX,y:t.clientY});const a=p.current;a&&a.requestPointerLock()},[c,d]);e.useEffect(()=>{const t=()=>{const n=document.pointerLockElement===p.current;A(n),n||(v.current.onScrub?.(0,!1),f.current=0,u.current=0)};return document.addEventListener("pointerlockchange",t),()=>{document.removeEventListener("pointerlockchange",t)}},[]),e.useEffect(()=>{if(!m)return;const t=a=>{const r=v.current,O=a.movementX,z=a.movementY,w=window.innerWidth,D=window.innerHeight;s.current+=O,s.current>w?s.current=s.current%w:s.current<0&&(s.current=w+s.current%w),N(S=>{let i=S.y+z;return i>D?i=i%D:i<0&&(i=D+i%D),{x:s.current,y:i}}),f.current+=O;const H=f.current/r.scrubSensitivity;if(Math.abs(H)>=1){let S=1;a.shiftKey?S=r.scrubShiftMultiplier:a.altKey&&(S=r.scrubAltMultiplier);const i=Math.trunc(H),V=i*r.scrubStep*S;let j=V;if(r.scrubMin!==void 0||r.scrubMax!==void 0){const B=u.current+V,W=Math.max(r.scrubMin??-1/0,Math.min(r.scrubMax??1/0,B));j=W-u.current,u.current=W}else u.current+=V;j!==0&&r.onScrub?.(j,!0),f.current=(H-i)*r.scrubSensitivity}},n=()=>{document.exitPointerLock()};return document.addEventListener("mousemove",t),document.addEventListener("mouseup",n),document.body.style.userSelect="none",()=>{document.removeEventListener("mousemove",t),document.removeEventListener("mouseup",n),document.body.style.userSelect=""}},[m]);const l=m?K.createPortal(e.createElement("div",{className:"rt-TextFieldSlotScrubCursor",style:{position:"fixed",left:k.x,top:k.y,transform:"translate(-50%, -50%)",pointerEvents:"none",zIndex:99999},"aria-hidden":"true"}),document.body):null;return e.createElement("div",{"data-accent-color":x,"data-side":y,"data-scrub":c||void 0,"data-scrubbing":m||void 0,...P,ref:Y(p,L),className:X("rt-TextFieldSlot",b),onPointerDown:c?C:void 0},P.children,l)});_.displayName="TextField.Slot";export{G as Root,_ as 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": "aAEA,UAAYA,MAAW,QACvB,OAAOC,MAAgB,aACvB,OAAS,eAAAC,MAAmB,oBAE5B,
|
|
6
|
-
"names": ["React", "classNames", "composeRefs", "textFieldRootPropDefs", "textFieldSlotPropDefs", "extractProps", "marginPropDefs", "TextFieldRoot", "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", "TextFieldSlot", "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": ["React", "ReactDOM", "classNames", "composeRefs", "textFieldRootPropDefs", "textFieldSlotPropDefs", "extractProps", "marginPropDefs", "TextFieldRoot", "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", "TextFieldSlot", "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
|
-
import{colorPropDef as r}from"../props/color.prop.js";import{paddingPropDefs as e}from"../props/padding.props.js";import{radiusPropDef as s}from"../props/radius.prop.js";import{flexPropDefs as
|
|
1
|
+
import{colorPropDef as r}from"../props/color.prop.js";import{paddingPropDefs as e}from"../props/padding.props.js";import{radiusPropDef as s}from"../props/radius.prop.js";import{flexPropDefs as t}from"./flex.props.js";const o=["1","2","3"],a=["classic","surface","soft","ghost","outline"],n=["solid","translucent"],p=["solid","translucent"],i={size:{type:"enum",className:"rt-r-size",values:o,default:"2",responsive:!0},variant:{type:"enum",className:"rt-variant",values:a,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},...r,...s,panelBackground:{type:"enum",values:n,default:void 0},material:{type:"enum",values:p,default:void 0}},l=["left","right"],f={side:{type:"enum",values:l},...r,gap:t.gap,px:e.px,pl:e.pl,pr:e.pr};export{i as textFieldRootPropDefs,f as textFieldSlotPropDefs};
|
|
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": "AAAA,OAAS,gBAAAA,MAAoB,yBAC7B,OAAS,mBAAAC,MAAuB,4BAChC,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,gBAAAC,MAAoB,kBAI7B,MAAMC,EAAQ,CAAC,IAAK,IAAK,GAAG,EACtBC,EAAW,CAAC,UAAW,UAAW,OAAQ,QAAS,SAAS,EAC5DC,EAAmB,CAAC,QAAS,aAAa,EAC1CC,EAAY,CAAC,QAAS,aAAa,EAEnCC,EAAwB,CAC5B,KAAM,CAAE,KAAM,OAAQ,UAAW,YAAa,OAAQJ,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,GAAGL,EACH,GAAGE,EACH,gBAAiB,CAAE,KAAM,OAAQ,OAAQI,EAAkB,QAAS,MAAU,EAC9E,SAAU,CAAE,KAAM,OAAQ,OAAQC,EAAW,QAAS,MAAU,CAClE,EAaME,EAAQ,CAAC,OAAQ,OAAO,EAExBC,EAAwB,CAC5B,KAAM,CAAE,KAAM,OAAQ,OAAQD,CAAM,EACpC,GAAGT,EACH,IAAKG,EAAa,IAClB,GAAIF,EAAgB,GACpB,GAAIA,EAAgB,GACpB,GAAIA,EAAgB,EACtB",
|
|
6
6
|
"names": ["colorPropDef", "paddingPropDefs", "radiusPropDef", "flexPropDefs", "sizes", "variants", "panelBackgrounds", "materials", "textFieldRootPropDefs", "sides", "textFieldSlotPropDefs"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kushagradhawan/kookie-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.79",
|
|
4
4
|
"description": "A modern React component library with beautiful design tokens, flexible theming, and comprehensive docs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"tsd": "^0.33.0",
|
|
192
192
|
"typescript": "^5.7.2",
|
|
193
193
|
"typescript-eslint": "^8.18.1",
|
|
194
|
-
"vitest": "^
|
|
194
|
+
"vitest": "^4.0.16"
|
|
195
195
|
},
|
|
196
196
|
"homepage": "https://github.com/KushagraDhawan1997/kookie-ui",
|
|
197
197
|
"repository": {
|
package/schemas/base-button.json
CHANGED
|
@@ -279,6 +279,6 @@
|
|
|
279
279
|
"title": "Base-button Component Props",
|
|
280
280
|
"description": "Props schema for the base-button component in Kookie UI",
|
|
281
281
|
"version": "1.0.0",
|
|
282
|
-
"generatedAt": "2025-12-
|
|
282
|
+
"generatedAt": "2025-12-24T18:38:01.486Z",
|
|
283
283
|
"source": "Zod schema"
|
|
284
284
|
}
|
package/schemas/button.json
CHANGED
|
@@ -530,6 +530,6 @@
|
|
|
530
530
|
"title": "Button Component Props",
|
|
531
531
|
"description": "Props schema for the button component in Kookie UI",
|
|
532
532
|
"version": "1.0.0",
|
|
533
|
-
"generatedAt": "2025-12-
|
|
533
|
+
"generatedAt": "2025-12-24T18:38:01.492Z",
|
|
534
534
|
"source": "Zod schema"
|
|
535
535
|
}
|
package/schemas/icon-button.json
CHANGED
|
@@ -313,6 +313,6 @@
|
|
|
313
313
|
"title": "Icon-button Component Props",
|
|
314
314
|
"description": "Props schema for the icon-button component in Kookie UI",
|
|
315
315
|
"version": "1.0.0",
|
|
316
|
-
"generatedAt": "2025-12-
|
|
316
|
+
"generatedAt": "2025-12-24T18:38:01.493Z",
|
|
317
317
|
"source": "Zod schema"
|
|
318
318
|
}
|
package/schemas/index.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"title": "Kookie UI Button Components",
|
|
4
4
|
"description": "Complete JSON Schema collection for all button components in Kookie UI",
|
|
5
5
|
"version": "1.0.0",
|
|
6
|
-
"generatedAt": "2025-12-
|
|
6
|
+
"generatedAt": "2025-12-24T18:38:01.496Z",
|
|
7
7
|
"source": "Zod schemas",
|
|
8
8
|
"components": {
|
|
9
9
|
"base-button": {
|
|
@@ -287,7 +287,7 @@
|
|
|
287
287
|
"title": "Base-button Component Props",
|
|
288
288
|
"description": "Props schema for the base-button component in Kookie UI",
|
|
289
289
|
"version": "1.0.0",
|
|
290
|
-
"generatedAt": "2025-12-
|
|
290
|
+
"generatedAt": "2025-12-24T18:38:01.486Z",
|
|
291
291
|
"source": "Zod schema"
|
|
292
292
|
},
|
|
293
293
|
"button": {
|
|
@@ -822,7 +822,7 @@
|
|
|
822
822
|
"title": "Button Component Props",
|
|
823
823
|
"description": "Props schema for the button component in Kookie UI",
|
|
824
824
|
"version": "1.0.0",
|
|
825
|
-
"generatedAt": "2025-12-
|
|
825
|
+
"generatedAt": "2025-12-24T18:38:01.492Z",
|
|
826
826
|
"source": "Zod schema"
|
|
827
827
|
},
|
|
828
828
|
"icon-button": {
|
|
@@ -1140,7 +1140,7 @@
|
|
|
1140
1140
|
"title": "Icon-button Component Props",
|
|
1141
1141
|
"description": "Props schema for the icon-button component in Kookie UI",
|
|
1142
1142
|
"version": "1.0.0",
|
|
1143
|
-
"generatedAt": "2025-12-
|
|
1143
|
+
"generatedAt": "2025-12-24T18:38:01.493Z",
|
|
1144
1144
|
"source": "Zod schema"
|
|
1145
1145
|
},
|
|
1146
1146
|
"toggle-button": {
|
|
@@ -1683,7 +1683,7 @@
|
|
|
1683
1683
|
"title": "Toggle-button Component Props",
|
|
1684
1684
|
"description": "Props schema for the toggle-button component in Kookie UI",
|
|
1685
1685
|
"version": "1.0.0",
|
|
1686
|
-
"generatedAt": "2025-12-
|
|
1686
|
+
"generatedAt": "2025-12-24T18:38:01.495Z",
|
|
1687
1687
|
"source": "Zod schema"
|
|
1688
1688
|
},
|
|
1689
1689
|
"toggle-icon-button": {
|
|
@@ -2009,7 +2009,7 @@
|
|
|
2009
2009
|
"title": "Toggle-icon-button Component Props",
|
|
2010
2010
|
"description": "Props schema for the toggle-icon-button component in Kookie UI",
|
|
2011
2011
|
"version": "1.0.0",
|
|
2012
|
-
"generatedAt": "2025-12-
|
|
2012
|
+
"generatedAt": "2025-12-24T18:38:01.496Z",
|
|
2013
2013
|
"source": "Zod schema"
|
|
2014
2014
|
}
|
|
2015
2015
|
}
|
|
@@ -538,6 +538,6 @@
|
|
|
538
538
|
"title": "Toggle-button Component Props",
|
|
539
539
|
"description": "Props schema for the toggle-button component in Kookie UI",
|
|
540
540
|
"version": "1.0.0",
|
|
541
|
-
"generatedAt": "2025-12-
|
|
541
|
+
"generatedAt": "2025-12-24T18:38:01.495Z",
|
|
542
542
|
"source": "Zod schema"
|
|
543
543
|
}
|
|
@@ -321,6 +321,6 @@
|
|
|
321
321
|
"title": "Toggle-icon-button Component Props",
|
|
322
322
|
"description": "Props schema for the toggle-icon-button component in Kookie UI",
|
|
323
323
|
"version": "1.0.0",
|
|
324
|
-
"generatedAt": "2025-12-
|
|
324
|
+
"generatedAt": "2025-12-24T18:38:01.496Z",
|
|
325
325
|
"source": "Zod schema"
|
|
326
326
|
}
|