@ryuzaki13/react-foundation-ui 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/Input-BmjlpA09.js.map +1 -1
- package/dist/chunks/Select-BJ5OqTe7.js +182 -0
- package/dist/chunks/Select-BJ5OqTe7.js.map +1 -0
- package/dist/chunks/{SerializableSelect-DkYeJtAO.js → SerializableSelect-CNe728Qa.js} +2 -2
- package/dist/chunks/{SerializableSelect-DkYeJtAO.js.map → SerializableSelect-CNe728Qa.js.map} +1 -1
- package/dist/chunks/{StateSelect-1jH3uLz9.js → StateSelect-ujAre258.js} +2 -2
- package/dist/chunks/{StateSelect-1jH3uLz9.js.map → StateSelect-ujAre258.js.map} +1 -1
- package/dist/chunks/{select-BT65bQ8J.js → select-BkLc6dyx.js} +2 -2
- package/dist/chunks/select-BkLc6dyx.js.map +1 -0
- package/dist/chunks/slider-CFKsfxFp.js.map +1 -1
- package/dist/expandable-action-panel/stories/ExpandableActionPanel.stories.js +1 -1
- package/dist/input/Input.d.ts +1 -1
- package/dist/input/Input.d.ts.map +1 -1
- package/dist/input/stories/Input.stories.js +1 -1
- package/dist/input/stories/Input.stories.js.map +1 -1
- package/dist/preset-select/index.js +1 -1
- package/dist/preset-select/index.js.map +1 -1
- package/dist/select/Select.d.ts +10 -5
- package/dist/select/Select.d.ts.map +1 -1
- package/dist/select/index.js +3 -3
- package/dist/select/stories/Select.stories.d.ts +1 -1
- package/dist/select/stories/Select.stories.js +1 -1
- package/dist/select/stories/SerializableSelect.stories.js +1 -1
- package/dist/slider/SliderInput.d.ts +2 -2
- package/dist/slider/SliderInput.d.ts.map +1 -1
- package/dist/slider/stories/SliderInput.stories.js.map +1 -1
- package/dist/state-select/index.js +1 -1
- package/dist/state-select/stories/StateSelect.stories.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/Select-CXeVjVKA.js +0 -182
- package/dist/chunks/Select-CXeVjVKA.js.map +0 -1
- package/dist/chunks/select-BT65bQ8J.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input-BmjlpA09.js","names":[],"sources":["../../src/input/Input.module.scss","../../src/input/lib/useInputFieldIds.ts","../../src/input/Input.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.controlLayout {\n\tposition: relative;\n\twidth: 100%;\n}\n\n.input {\n\theight: var(--control-height);\n\twidth: 100%;\n\tpadding: var(--space-xs) var(--space-sm);\n\tfont-size: var(--font-size-md);\n\n\t--ui-color: var(--content-0);\n\t--ui-color-hover: var(--content-0);\n\t--ui-color-active: var(--content-0);\n}\n\n.inputNumber {\n\tappearance: textfield;\n\t-moz-appearance: textfield;\n\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n}\n\n.controlWithEndAdornment {\n\tpadding-right: calc(var(--input-end-adornment-width, var(--control-height)) + var(--space-sm));\n}\n\n.controlEndAdornment {\n\tposition: absolute;\n\theight: 100%;\n\ttop: 0;\n\tright: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n\t// max-width: calc(100% - (var(--space-md) * 2));\n\tmax-width: calc(100% - var(--space-md));\n}\n\n.endAdornmentGroup {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n}\n\n.clearButton {\n\twidth: 1.75em;\n\theight: 1.75em;\n\tborder: none;\n\tbackground: transparent;\n\tcolor: var(--content-1);\n\ttransition:\n\t\tcolor var(--transition-fast) ease,\n\t\tbackground-color var(--transition-fast) ease;\n\n\t&:hover {\n\t\tcolor: var(--content-accent);\n\t\tbackground-color: var(--status-info-soft);\n\t}\n\n\t&:focus-visible {\n\t\t@include focusVisible;\n\t}\n\n\t&:disabled {\n\t\tpointer-events: none;\n\t\topacity: 0.25;\n\t}\n}\n\n.error {\n\tposition: absolute;\n\tz-index: 11;\n\tbottom: calc(var(--space-xs) * -1);\n\tleft: 0;\n\tright: 0;\n\ttransform: translateY(100%);\n\t// font-size: var(--font-size-sm);\n\tcolor: var(--status-error-on-fill);\n\tbackground: var(--status-error-fill);\n\tborder-radius: var(--radius-sm);\n\tpadding: var(--space-xs) var(--space-sm);\n\tbox-shadow: var(--shadow-sm);\n\topacity: 0.9;\n}\n","import { useId } from \"react\";\n\nexport interface UseInputFieldIdsOptions {\n\tid?: string;\n\thasLabel?: boolean;\n\thasDescription?: boolean;\n\thasError?: boolean;\n}\n\nexport interface InputFieldIds {\n\tcontrolId: string;\n\tlabelId?: string;\n\tdescriptionId?: string;\n\terrorId?: string;\n\tdescribedBy?: string;\n}\n\nexport function useInputFieldIds({ id: externalId, hasLabel, hasDescription, hasError }: UseInputFieldIdsOptions): InputFieldIds {\n\tconst autoId = useId();\n\tconst controlId = externalId ?? autoId;\n\tconst labelId = hasLabel ? `${controlId}-label` : undefined;\n\tconst descriptionId = hasDescription ? `${controlId}-description` : undefined;\n\tconst errorId = hasError ? `${controlId}-error` : undefined;\n\tconst describedBy = [descriptionId, errorId].filter(Boolean).join(\" \") || undefined;\n\n\treturn {\n\t\tcontrolId,\n\t\tlabelId,\n\t\tdescriptionId,\n\t\terrorId,\n\t\tdescribedBy\n\t};\n}\n","import React, { CSSProperties, InputHTMLAttributes, ReactNode, useEffect, useEffectEvent, useState } from \"react\";\n\nimport { toFiniteNumber } from \"@ryuzaki13/react-foundation-lib/formatters\";\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { XIcon } from \"lucide-react\";\n\nimport { UiBaseProps, UiSize } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./Input.module.scss\";\nimport { useInputFieldIds } from \"./lib/useInputFieldIds\";\n\nexport interface InputUIProps extends Omit<UiBaseProps<never>, \"value\" | \"onChange\"> {\n\tclassName?: string;\n\terror?: string;\n\tcontrolId?: string;\n\tlabelId?: string;\n\tdescriptionId?: string;\n\terrorId?: string;\n\tchildren: React.ReactNode;\n}\n\nexport interface InputControlRenderProps {\n\tcontrolClassName?: string;\n}\n\nexport interface InputControlProps {\n\tclassName?: string;\n\tendAdornment?: ReactNode;\n\tendAdornmentClassName?: string;\n\tendAdornmentWidth?: string;\n\tchildren: (props: InputControlRenderProps) => ReactNode;\n}\n\nexport interface InputClearButtonProps {\n\tonClick?: () => void;\n\tdisabled?: boolean;\n\tclassName?: string;\n\tariaLabel?: string;\n}\n\nfunction InputLabel({ label, controlId, labelId }: { label: React.ReactNode; controlId?: string; labelId?: string }) {\n\treturn (\n\t\t<label id={labelId} htmlFor={controlId} className={uiStyles.uiLabel}>\n\t\t\t{label}\n\t\t</label>\n\t);\n}\n\nexport function InputUILoading({\n\tlabel,\n\tdescription,\n\tsize,\n\tdisabled,\n\tclassName\n}: Pick<InputUIProps, \"label\" | \"description\" | \"size\" | \"disabled\" | \"className\">) {\n\tconst { controlId, labelId, descriptionId } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description\n\t});\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(uiStyles.uiElement, uiStyles.uiSizable, size && uiStyles[size as UiSize], uiStyles.disabled, className)}\n\t\t\taria-disabled={disabled || undefined}>\n\t\t\t{label && <InputLabel label={label} controlId={controlId} labelId={labelId} />}\n\t\t\t{description && (\n\t\t\t\t<p id={descriptionId} className={uiStyles.uiDescription}>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<div className={cn(uiStyles.uiInputControlFake, \"skeletonLine\")} />\n\t\t</div>\n\t);\n}\n\n/**\n * Низкоуровневая оболочка поля ввода с общими элементами оформления.\n */\nexport function InputUI({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\terror,\n\tsize,\n\tcontrolId,\n\tlabelId,\n\tdescriptionId,\n\terrorId,\n\tchildren\n}: InputUIProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tuiStyles.uiElement,\n\t\t\t\tuiStyles.uiSizable,\n\t\t\t\tsize && uiStyles[size as UiSize],\n\t\t\t\tdisabled && uiStyles.disabled,\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\taria-disabled={disabled || undefined}>\n\t\t\t{label && <InputLabel label={label} controlId={controlId} labelId={labelId} />}\n\t\t\t{description && (\n\t\t\t\t<p id={descriptionId} className={uiStyles.uiDescription}>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<div className={styles.controlLayout}>\n\t\t\t\t{children}\n\n\t\t\t\t{error && (\n\t\t\t\t\t<p id={errorId} className={styles.error} role=\"alert\">\n\t\t\t\t\t\t{error}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport function InputControl({ className, endAdornment, endAdornmentClassName, endAdornmentWidth, children }: InputControlProps) {\n\tconst hasEndAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst style =\n\t\thasEndAdornment && endAdornmentWidth ? ({ \"--input-end-adornment-width\": endAdornmentWidth } as CSSProperties) : undefined;\n\n\treturn (\n\t\t<div className={cn(styles.controlLayout, className)} style={style}>\n\t\t\t{children({ controlClassName: hasEndAdornment ? styles.controlWithEndAdornment : undefined })}\n\t\t\t{hasEndAdornment && <div className={cn(styles.controlEndAdornment, endAdornmentClassName)}>{endAdornment}</div>}\n\t\t</div>\n\t);\n}\n\nexport function InputClearButton({ onClick, disabled, className, ariaLabel = \"Очистить значение\" }: InputClearButtonProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tdisabled={disabled || !onClick}\n\t\t\tclassName={cn(styles.clearButton, \"flexCenter radiusSm\", className)}\n\t\t\tonClick={onClick}\n\t\t\taria-label={ariaLabel}>\n\t\t\t<XIcon />\n\t\t</button>\n\t);\n}\n\nfunction resolveEndAdornmentWidth(hasAdornment: boolean, hasClearAction: boolean, explicitWidth?: string) {\n\tif (explicitWidth) {\n\t\treturn explicitWidth;\n\t}\n\n\tif (hasAdornment && hasClearAction) {\n\t\treturn \"calc((var(--control-height) * 2) + var(--space-xs))\";\n\t}\n\n\tif (hasAdornment || hasClearAction) {\n\t\treturn \"var(--control-height)\";\n\t}\n\n\treturn undefined;\n}\n\nfunction createEndAdornment({ endAdornment, onClear, disabled }: { endAdornment?: ReactNode; onClear?: () => void; disabled?: boolean }) {\n\tif ((endAdornment === undefined || endAdornment === null) && !onClear) {\n\t\treturn undefined;\n\t}\n\n\treturn (\n\t\t<div className={styles.endAdornmentGroup}>\n\t\t\t{endAdornment}\n\t\t\t{onClear && <InputClearButton onClick={onClear} disabled={disabled} />}\n\t\t</div>\n\t);\n}\n\nexport interface BaseInputProps<T extends number | string, V = T>\n\textends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\" | \"value\" | \"type\" | \"defaultValue\" | \"onChange\">, UiBaseProps<T, V> {\n\tonClear?: () => void;\n\terror?: string;\n\tonClearError?: () => void;\n\tdefaultValue?: T;\n\tendAdornment?: ReactNode;\n\tendAdornmentClassName?: string;\n\tendAdornmentWidth?: string;\n}\n\nexport interface InputTextProps extends BaseInputProps<string> {\n\ttype?: \"email\" | \"password\" | \"search\" | \"tel\" | \"text\" | \"url\";\n\n\t/**\n\t * Регулярное выражение для валидации всего введённого значения.\n\t * При несоответствии поле подсвечивается как невалидное, но текст не удаляется.\n\t * Пример: `/^\\d*$/`\n\t */\n\tallowedPattern?: RegExp;\n}\n\n/**\n * Базовое текстовое поле ввода для строковых значений.\n */\nexport function InputText({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\tonClear,\n\terror,\n\tonClearError,\n\tonChange,\n\tvalue,\n\tsize,\n\tallowedPattern,\n\tendAdornment,\n\tendAdornmentClassName,\n\tendAdornmentWidth,\n\ttype = \"text\",\n\t...props\n}: InputTextProps) {\n\tconst [internalInvalid, setInternalInvalid] = useState(false);\n\n\tconst handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst newValue = e.target.value;\n\n\t\tif (allowedPattern !== undefined) {\n\t\t\tsetInternalInvalid(newValue !== \"\" && !allowedPattern.test(newValue));\n\t\t}\n\n\t\tonChange?.(newValue);\n\t\tif (error && onClearError) onClearError();\n\t};\n\n\tconst hasValue = Boolean(value && value.length > 0);\n\tconst visibleError = hasValue ? error : undefined;\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: props.id,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!visibleError\n\t});\n\tconst isInvalid = hasValue && (!!error || internalInvalid);\n\tconst resolvedEndAdornment = createEndAdornment({ endAdornment, onClear, disabled });\n\tconst hasCustomAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst resolvedEndAdornmentWidth = resolveEndAdornmentWidth(hasCustomAdornment, !!onClear, endAdornmentWidth);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={visibleError}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={resolvedEndAdornment}\n\t\t\t\tendAdornmentClassName={endAdornmentClassName}\n\t\t\t\tendAdornmentWidth={resolvedEndAdornmentWidth}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<input\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\taria-invalid={isInvalid || undefined}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tdata-invalid={isInvalid ? \"\" : undefined}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.input, controlClassName)}\n\t\t\t\t\t\tonChange={handleInput}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\n/**\n * Числовое поле ввода с нормализацией значения и защитой от промежуточного невалидного ввода.\n */\nexport function InputNumber({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\tonClear,\n\terror,\n\tonClearError,\n\tonChange,\n\tvalue,\n\tsize,\n\tendAdornment,\n\tendAdornmentClassName,\n\tendAdornmentWidth,\n\t...props\n}: BaseInputProps<number, number | undefined>) {\n\tconst inputProps = props as InputHTMLAttributes<HTMLInputElement>;\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: props.id,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\tconst [rawValue, setRawValue] = useState<string>(() => String(value));\n\t// const [internalInvalid, setInternalInvalid] = useState(false);\n\n\tconst syncRawValue = useEffectEvent((nextRaw: string) => {\n\t\tsetRawValue(nextRaw);\n\t\t// setInternalInvalid(false);\n\t});\n\n\tuseEffect(() => {\n\t\tconst nextRaw = value !== undefined && typeof value === \"number\" && !isNaN(value) ? String(value) : \"\";\n\t\tsyncRawValue(nextRaw);\n\t}, [value]);\n\n\tconst handleClear = onClear\n\t\t? () => {\n\t\t\t\tsetRawValue(\"\");\n\t\t\t\t// setInternalInvalid(false);\n\t\t\t\tonClear();\n\t\t\t}\n\t\t: undefined;\n\n\tconst handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst raw = e.target.value;\n\t\tsetRawValue(raw);\n\n\t\tconst parsed = toFiniteNumber(raw) ?? value ?? 0;\n\t\t// const isEmpty = raw.trim() === \"\";\n\n\t\t// const minNum = min !== undefined ? Number(min) : undefined;\n\t\t// const maxNum = max !== undefined ? Number(max) : undefined;\n\t\t// const isValidNumber = !isEmpty && !isNaN(parsed);\n\t\t// const isInRange = isValidNumber && (minNum === undefined || parsed >= minNum) && (maxNum === undefined || parsed <= maxNum);\n\n\t\t// setInternalInvalid(!isEmpty && (!isValidNumber || !isInRange));\n\n\t\tonChange?.(parsed);\n\t\tif (error && onClearError) onClearError();\n\t};\n\n\t// const isInvalid = !!error || internalInvalid;\n\tconst resolvedEndAdornment = createEndAdornment({ endAdornment, onClear: handleClear, disabled });\n\tconst hasCustomAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst resolvedEndAdornmentWidth = resolveEndAdornmentWidth(hasCustomAdornment, !!handleClear, endAdornmentWidth);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={resolvedEndAdornment}\n\t\t\t\tendAdornmentClassName={endAdornmentClassName}\n\t\t\t\tendAdornmentWidth={resolvedEndAdornmentWidth}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<input\n\t\t\t\t\t\t{...inputProps}\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tinputMode=\"decimal\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tvalue={rawValue}\n\t\t\t\t\t\t// aria-invalid={isInvalid || undefined}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.input, styles.inputNumber, controlClassName)}\n\t\t\t\t\t\tonChange={handleInput}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\n/**\n * Совместимый алиас для `InputText`.\n */\nexport const Input = InputText;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Input-BmjlpA09.js","names":[],"sources":["../../src/input/Input.module.scss","../../src/input/lib/useInputFieldIds.ts","../../src/input/Input.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.controlLayout {\n\tposition: relative;\n\twidth: 100%;\n}\n\n.input {\n\theight: var(--control-height);\n\twidth: 100%;\n\tpadding: var(--space-xs) var(--space-sm);\n\tfont-size: var(--font-size-md);\n\n\t--ui-color: var(--content-0);\n\t--ui-color-hover: var(--content-0);\n\t--ui-color-active: var(--content-0);\n}\n\n.inputNumber {\n\tappearance: textfield;\n\t-moz-appearance: textfield;\n\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n}\n\n.controlWithEndAdornment {\n\tpadding-right: calc(var(--input-end-adornment-width, var(--control-height)) + var(--space-sm));\n}\n\n.controlEndAdornment {\n\tposition: absolute;\n\theight: 100%;\n\ttop: 0;\n\tright: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n\t// max-width: calc(100% - (var(--space-md) * 2));\n\tmax-width: calc(100% - var(--space-md));\n}\n\n.endAdornmentGroup {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n}\n\n.clearButton {\n\twidth: 1.75em;\n\theight: 1.75em;\n\tborder: none;\n\tbackground: transparent;\n\tcolor: var(--content-1);\n\ttransition:\n\t\tcolor var(--transition-fast) ease,\n\t\tbackground-color var(--transition-fast) ease;\n\n\t&:hover {\n\t\tcolor: var(--content-accent);\n\t\tbackground-color: var(--status-info-soft);\n\t}\n\n\t&:focus-visible {\n\t\t@include focusVisible;\n\t}\n\n\t&:disabled {\n\t\tpointer-events: none;\n\t\topacity: 0.25;\n\t}\n}\n\n.error {\n\tposition: absolute;\n\tz-index: 11;\n\tbottom: calc(var(--space-xs) * -1);\n\tleft: 0;\n\tright: 0;\n\ttransform: translateY(100%);\n\t// font-size: var(--font-size-sm);\n\tcolor: var(--status-error-on-fill);\n\tbackground: var(--status-error-fill);\n\tborder-radius: var(--radius-sm);\n\tpadding: var(--space-xs) var(--space-sm);\n\tbox-shadow: var(--shadow-sm);\n\topacity: 0.9;\n}\n","import { useId } from \"react\";\n\nexport interface UseInputFieldIdsOptions {\n\tid?: string;\n\thasLabel?: boolean;\n\thasDescription?: boolean;\n\thasError?: boolean;\n}\n\nexport interface InputFieldIds {\n\tcontrolId: string;\n\tlabelId?: string;\n\tdescriptionId?: string;\n\terrorId?: string;\n\tdescribedBy?: string;\n}\n\nexport function useInputFieldIds({ id: externalId, hasLabel, hasDescription, hasError }: UseInputFieldIdsOptions): InputFieldIds {\n\tconst autoId = useId();\n\tconst controlId = externalId ?? autoId;\n\tconst labelId = hasLabel ? `${controlId}-label` : undefined;\n\tconst descriptionId = hasDescription ? `${controlId}-description` : undefined;\n\tconst errorId = hasError ? `${controlId}-error` : undefined;\n\tconst describedBy = [descriptionId, errorId].filter(Boolean).join(\" \") || undefined;\n\n\treturn {\n\t\tcontrolId,\n\t\tlabelId,\n\t\tdescriptionId,\n\t\terrorId,\n\t\tdescribedBy\n\t};\n}\n","import React, { CSSProperties, InputHTMLAttributes, ReactNode, useEffect, useEffectEvent, useState } from \"react\";\n\nimport { toFiniteNumber } from \"@ryuzaki13/react-foundation-lib/formatters\";\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { XIcon } from \"lucide-react\";\n\nimport { UiBaseProps, UiSize } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./Input.module.scss\";\nimport { useInputFieldIds } from \"./lib/useInputFieldIds\";\n\nexport interface InputUIProps extends Omit<UiBaseProps<never>, \"value\" | \"onChange\"> {\n\tclassName?: string;\n\terror?: string;\n\tcontrolId?: string;\n\tlabelId?: string;\n\tdescriptionId?: string;\n\terrorId?: string;\n\tchildren: React.ReactNode;\n}\n\nexport interface InputControlRenderProps {\n\tcontrolClassName?: string;\n}\n\nexport interface InputControlProps {\n\tclassName?: string;\n\tendAdornment?: ReactNode;\n\tendAdornmentClassName?: string;\n\tendAdornmentWidth?: string;\n\tchildren: (props: InputControlRenderProps) => ReactNode;\n}\n\nexport interface InputClearButtonProps {\n\tonClick?: () => void;\n\tdisabled?: boolean;\n\tclassName?: string;\n\tariaLabel?: string;\n}\n\nfunction InputLabel({ label, controlId, labelId }: { label: React.ReactNode; controlId?: string; labelId?: string }) {\n\treturn (\n\t\t<label id={labelId} htmlFor={controlId} className={uiStyles.uiLabel}>\n\t\t\t{label}\n\t\t</label>\n\t);\n}\n\nexport function InputUILoading({\n\tlabel,\n\tdescription,\n\tsize,\n\tdisabled,\n\tclassName\n}: Pick<InputUIProps, \"label\" | \"description\" | \"size\" | \"disabled\" | \"className\">) {\n\tconst { controlId, labelId, descriptionId } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description\n\t});\n\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(uiStyles.uiElement, uiStyles.uiSizable, size && uiStyles[size as UiSize], uiStyles.disabled, className)}\n\t\t\taria-disabled={disabled || undefined}>\n\t\t\t{label && <InputLabel label={label} controlId={controlId} labelId={labelId} />}\n\t\t\t{description && (\n\t\t\t\t<p id={descriptionId} className={uiStyles.uiDescription}>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<div className={cn(uiStyles.uiInputControlFake, \"skeletonLine\")} />\n\t\t</div>\n\t);\n}\n\n/**\n * Низкоуровневая оболочка поля ввода с общими элементами оформления.\n */\nexport function InputUI({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\terror,\n\tsize,\n\tcontrolId,\n\tlabelId,\n\tdescriptionId,\n\terrorId,\n\tchildren\n}: InputUIProps) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn(\n\t\t\t\tuiStyles.uiElement,\n\t\t\t\tuiStyles.uiSizable,\n\t\t\t\tsize && uiStyles[size as UiSize],\n\t\t\t\tdisabled && uiStyles.disabled,\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\taria-disabled={disabled || undefined}>\n\t\t\t{label && <InputLabel label={label} controlId={controlId} labelId={labelId} />}\n\t\t\t{description && (\n\t\t\t\t<p id={descriptionId} className={uiStyles.uiDescription}>\n\t\t\t\t\t{description}\n\t\t\t\t</p>\n\t\t\t)}\n\t\t\t<div className={styles.controlLayout}>\n\t\t\t\t{children}\n\n\t\t\t\t{error && (\n\t\t\t\t\t<p id={errorId} className={styles.error} role=\"alert\">\n\t\t\t\t\t\t{error}\n\t\t\t\t\t</p>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nexport function InputControl({ className, endAdornment, endAdornmentClassName, endAdornmentWidth, children }: InputControlProps) {\n\tconst hasEndAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst style =\n\t\thasEndAdornment && endAdornmentWidth ? ({ \"--input-end-adornment-width\": endAdornmentWidth } as CSSProperties) : undefined;\n\n\treturn (\n\t\t<div className={cn(styles.controlLayout, className)} style={style}>\n\t\t\t{children({ controlClassName: hasEndAdornment ? styles.controlWithEndAdornment : undefined })}\n\t\t\t{hasEndAdornment && <div className={cn(styles.controlEndAdornment, endAdornmentClassName)}>{endAdornment}</div>}\n\t\t</div>\n\t);\n}\n\nexport function InputClearButton({ onClick, disabled, className, ariaLabel = \"Очистить значение\" }: InputClearButtonProps) {\n\treturn (\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tdisabled={disabled || !onClick}\n\t\t\tclassName={cn(styles.clearButton, \"flexCenter radiusSm\", className)}\n\t\t\tonClick={onClick}\n\t\t\taria-label={ariaLabel}>\n\t\t\t<XIcon />\n\t\t</button>\n\t);\n}\n\nfunction resolveEndAdornmentWidth(hasAdornment: boolean, hasClearAction: boolean, explicitWidth?: string) {\n\tif (explicitWidth) {\n\t\treturn explicitWidth;\n\t}\n\n\tif (hasAdornment && hasClearAction) {\n\t\treturn \"calc((var(--control-height) * 2) + var(--space-xs))\";\n\t}\n\n\tif (hasAdornment || hasClearAction) {\n\t\treturn \"var(--control-height)\";\n\t}\n\n\treturn undefined;\n}\n\nfunction createEndAdornment({ endAdornment, onClear, disabled }: { endAdornment?: ReactNode; onClear?: () => void; disabled?: boolean }) {\n\tif ((endAdornment === undefined || endAdornment === null) && !onClear) {\n\t\treturn undefined;\n\t}\n\n\treturn (\n\t\t<div className={styles.endAdornmentGroup}>\n\t\t\t{endAdornment}\n\t\t\t{onClear && <InputClearButton onClick={onClear} disabled={disabled} />}\n\t\t</div>\n\t);\n}\n\nexport interface BaseInputProps<T extends number | string, V = T>\n\textends Omit<InputHTMLAttributes<HTMLInputElement>, \"size\" | \"value\" | \"type\" | \"defaultValue\" | \"onChange\">, UiBaseProps<T, V> {\n\tonClear?: () => void;\n\terror?: string;\n\tonClearError?: () => void;\n\tdefaultValue?: T;\n\tendAdornment?: ReactNode;\n\tendAdornmentClassName?: string;\n\tendAdornmentWidth?: string;\n}\n\nexport interface InputTextProps extends BaseInputProps<string> {\n\ttype?: \"email\" | \"password\" | \"search\" | \"tel\" | \"text\" | \"url\";\n\n\t/**\n\t * Регулярное выражение для валидации всего введённого значения.\n\t * При несоответствии поле подсвечивается как невалидное, но текст не удаляется.\n\t * Пример: `/^\\d*$/`\n\t */\n\tallowedPattern?: RegExp;\n}\n\n/**\n * Базовое текстовое поле ввода для строковых значений.\n */\nexport function InputText({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\tonClear,\n\terror,\n\tonClearError,\n\tonChange,\n\tvalue,\n\tsize,\n\tallowedPattern,\n\tendAdornment,\n\tendAdornmentClassName,\n\tendAdornmentWidth,\n\ttype = \"text\",\n\t...props\n}: InputTextProps) {\n\tconst [internalInvalid, setInternalInvalid] = useState(false);\n\n\tconst handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst newValue = e.target.value;\n\n\t\tif (allowedPattern !== undefined) {\n\t\t\tsetInternalInvalid(newValue !== \"\" && !allowedPattern.test(newValue));\n\t\t}\n\n\t\tonChange?.(newValue);\n\t\tif (error && onClearError) onClearError();\n\t};\n\n\tconst hasValue = Boolean(value && value.length > 0);\n\tconst visibleError = hasValue ? error : undefined;\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: props.id,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!visibleError\n\t});\n\tconst isInvalid = hasValue && (!!error || internalInvalid);\n\tconst resolvedEndAdornment = createEndAdornment({ endAdornment, onClear, disabled });\n\tconst hasCustomAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst resolvedEndAdornmentWidth = resolveEndAdornmentWidth(hasCustomAdornment, !!onClear, endAdornmentWidth);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={visibleError}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={resolvedEndAdornment}\n\t\t\t\tendAdornmentClassName={endAdornmentClassName}\n\t\t\t\tendAdornmentWidth={resolvedEndAdornmentWidth}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<input\n\t\t\t\t\t\t{...props}\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tvalue={value}\n\t\t\t\t\t\taria-invalid={isInvalid || undefined}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tdata-invalid={isInvalid ? \"\" : undefined}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.input, controlClassName)}\n\t\t\t\t\t\tonChange={handleInput}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\n/**\n * Числовое поле ввода с нормализацией значения и защитой от промежуточного невалидного ввода.\n */\nexport function InputNumber({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tclassName,\n\tonClear,\n\terror,\n\tonClearError,\n\tonChange,\n\tvalue,\n\tsize,\n\tendAdornment,\n\tendAdornmentClassName,\n\tendAdornmentWidth,\n\t...props\n}: BaseInputProps<number>) {\n\tconst inputProps = props as InputHTMLAttributes<HTMLInputElement>;\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\tid: props.id,\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\tconst [rawValue, setRawValue] = useState<string>(() => String(value));\n\t// const [internalInvalid, setInternalInvalid] = useState(false);\n\n\tconst syncRawValue = useEffectEvent((nextRaw: string) => {\n\t\tsetRawValue(nextRaw);\n\t\t// setInternalInvalid(false);\n\t});\n\n\tuseEffect(() => {\n\t\tconst nextRaw = value !== undefined && typeof value === \"number\" && !isNaN(value) ? String(value) : \"\";\n\t\tsyncRawValue(nextRaw);\n\t}, [value]);\n\n\tconst handleClear = onClear\n\t\t? () => {\n\t\t\t\tsetRawValue(\"\");\n\t\t\t\t// setInternalInvalid(false);\n\t\t\t\tonClear();\n\t\t\t}\n\t\t: undefined;\n\n\tconst handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\tconst raw = e.target.value;\n\t\tsetRawValue(raw);\n\n\t\tconst parsed = toFiniteNumber(raw) ?? value ?? 0;\n\t\t// const isEmpty = raw.trim() === \"\";\n\n\t\t// const minNum = min !== undefined ? Number(min) : undefined;\n\t\t// const maxNum = max !== undefined ? Number(max) : undefined;\n\t\t// const isValidNumber = !isEmpty && !isNaN(parsed);\n\t\t// const isInRange = isValidNumber && (minNum === undefined || parsed >= minNum) && (maxNum === undefined || parsed <= maxNum);\n\n\t\t// setInternalInvalid(!isEmpty && (!isValidNumber || !isInRange));\n\n\t\tonChange?.(parsed);\n\t\tif (error && onClearError) onClearError();\n\t};\n\n\t// const isInvalid = !!error || internalInvalid;\n\tconst resolvedEndAdornment = createEndAdornment({ endAdornment, onClear: handleClear, disabled });\n\tconst hasCustomAdornment = endAdornment !== undefined && endAdornment !== null;\n\tconst resolvedEndAdornmentWidth = resolveEndAdornmentWidth(hasCustomAdornment, !!handleClear, endAdornmentWidth);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={resolvedEndAdornment}\n\t\t\t\tendAdornmentClassName={endAdornmentClassName}\n\t\t\t\tendAdornmentWidth={resolvedEndAdornmentWidth}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<input\n\t\t\t\t\t\t{...inputProps}\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t\tinputMode=\"decimal\"\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tvalue={rawValue}\n\t\t\t\t\t\t// aria-invalid={isInvalid || undefined}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.input, styles.inputNumber, controlClassName)}\n\t\t\t\t\t\tonChange={handleInput}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\n/**\n * Совместимый алиас для `InputText`.\n */\nexport const Input = InputText;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { t as e } from "./ui.module-BisoTevy.js";
|
|
2
|
+
import { a as t, c as n, d as r, f as i, i as a, l as o, o as s, r as c, t as ee, u as te } from "./picker-Dg55Ss-B.js";
|
|
3
|
+
import { useRef as ne, useState as l } from "react";
|
|
4
|
+
import { cn as u } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
|
+
import { CheckIcon as re, XIcon as ie } from "lucide-react";
|
|
6
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
7
|
+
//#region src/select/lib/getOptionSearchText.ts
|
|
8
|
+
function m({ option: e, getOptionLabel: t, getOptionCode: n }) {
|
|
9
|
+
return [s(t(e)), s(n?.(e))].filter((e) => !!e).join(" ").toLowerCase();
|
|
10
|
+
}
|
|
11
|
+
function h(e, t, n) {
|
|
12
|
+
return e.find((e) => e.value === t) ?? n;
|
|
13
|
+
}
|
|
14
|
+
var g = {
|
|
15
|
+
inputWithOverlay: "aEEqH1",
|
|
16
|
+
valueOverlay: "_4HQKa7"
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/select/Select.tsx
|
|
20
|
+
function _(h) {
|
|
21
|
+
let { label: _, description: ae, disabled: v, placeholder: y, size: oe, options: b, value: x, onChange: S, getOptionKey: C, getOptionLabel: w, getOptionCode: T, getOptionDisabled: E, getOptionAriaLabel: se, getOptionClassName: ce, renderOption: D, renderValue: O, className: le, buttonClassName: ue, optionsClassName: de, optionsContentClassName: fe, searchable: k = !1, defaultFilter: pe = !0, query: me, defaultQuery: he, onQuery: ge, renderPopupHeader: A, emptyState: j, loadingState: M, errorState: N, placement: P = "bottom-start", clearable: F = !1 } = h, I = S, L = ne(null), [R, _e] = l(!1), z = k ? "search-single" : "display", B = x === void 0 ? void 0 : C(x), V = B === void 0 ? void 0 : b.find((e) => C(e) === B) ?? x, { query: H, setQuery: U } = c({
|
|
22
|
+
open: R,
|
|
23
|
+
query: me,
|
|
24
|
+
defaultQuery: he,
|
|
25
|
+
onQuery: ge,
|
|
26
|
+
triggerMode: z
|
|
27
|
+
}), W = t({
|
|
28
|
+
options: b,
|
|
29
|
+
query: H,
|
|
30
|
+
enabled: k && pe,
|
|
31
|
+
getSearchText: (e) => m({
|
|
32
|
+
option: e,
|
|
33
|
+
getOptionLabel: w,
|
|
34
|
+
getOptionCode: T
|
|
35
|
+
})
|
|
36
|
+
}), { activeIndex: ve, context: ye, floatingStyles: be, getFloatingProps: xe, setReference: Se, setFloating: Ce, setOptionRef: we, close: G, openList: Te, toggleOpen: Ee, selectOption: De, selectActiveOption: Oe, handleReferenceKeyDown: ke, handleFloatingKeyDown: Ae, getOptionId: je, getActiveOptionId: K } = a({
|
|
37
|
+
options: W,
|
|
38
|
+
selectedIndex: B === void 0 ? -1 : W.findIndex((e) => C(e) === B),
|
|
39
|
+
open: R,
|
|
40
|
+
onOpenChange: _e,
|
|
41
|
+
getOptionDisabled: E,
|
|
42
|
+
onSelect: I,
|
|
43
|
+
disabled: v,
|
|
44
|
+
placement: P,
|
|
45
|
+
triggerMode: z
|
|
46
|
+
}), q = W.length > 0, J = V === void 0 ? void 0 : w(V), Y = V === void 0 ? void 0 : O ? O(V) : J, Me = s(J), Ne = V === void 0 ? void 0 : s(T?.(V)), X = s(Y) ?? Me ?? Ne ?? (B === void 0 ? "" : String(B)), Z = k && (R || H.length > 0), Pe = Z ? H : V === void 0 ? "" : X, Q = V !== void 0 && Y !== void 0 && s(Y) === void 0 && !Z, $ = ee({
|
|
47
|
+
mode: z,
|
|
48
|
+
open: R,
|
|
49
|
+
currentQuery: H,
|
|
50
|
+
hasDisplayValue: V !== void 0,
|
|
51
|
+
inputRef: L,
|
|
52
|
+
setQuery: U,
|
|
53
|
+
openList: Te,
|
|
54
|
+
close: G,
|
|
55
|
+
toggleOpen: Ee
|
|
56
|
+
}), Fe = (e) => {
|
|
57
|
+
L.current = e;
|
|
58
|
+
}, Ie = () => {
|
|
59
|
+
F && I(void 0), U(""), G();
|
|
60
|
+
};
|
|
61
|
+
return /* @__PURE__ */ f(i, {
|
|
62
|
+
label: _,
|
|
63
|
+
description: ae,
|
|
64
|
+
disabled: v,
|
|
65
|
+
placeholder: y,
|
|
66
|
+
size: oe,
|
|
67
|
+
className: le,
|
|
68
|
+
children: ({ controlId: t, labelId: i, describedBy: a }) => {
|
|
69
|
+
let s = `${t}-listbox`;
|
|
70
|
+
return /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(n, {
|
|
71
|
+
ref: Fe,
|
|
72
|
+
rootRef: Se,
|
|
73
|
+
id: t,
|
|
74
|
+
type: "text",
|
|
75
|
+
disabled: v,
|
|
76
|
+
readOnly: !k,
|
|
77
|
+
autoComplete: "off",
|
|
78
|
+
role: "combobox",
|
|
79
|
+
value: Pe,
|
|
80
|
+
placeholder: V === void 0 || Z ? y : void 0,
|
|
81
|
+
"aria-labelledby": i,
|
|
82
|
+
"aria-describedby": a,
|
|
83
|
+
"aria-haspopup": "listbox",
|
|
84
|
+
"aria-expanded": R,
|
|
85
|
+
"aria-controls": R ? s : void 0,
|
|
86
|
+
"aria-autocomplete": k ? "list" : "none",
|
|
87
|
+
"aria-activedescendant": R ? K(s) : void 0,
|
|
88
|
+
inputClassName: u(Q && g.inputWithOverlay, ue, "textOverflow"),
|
|
89
|
+
overlay: Q ? /* @__PURE__ */ f("div", {
|
|
90
|
+
className: g.valueOverlay,
|
|
91
|
+
children: Y
|
|
92
|
+
}) : void 0,
|
|
93
|
+
endAdornment: /* @__PURE__ */ f(o, {
|
|
94
|
+
open: R,
|
|
95
|
+
disabled: v,
|
|
96
|
+
onToggleMouseDown: $.handleToggleMouseDown,
|
|
97
|
+
onToggleClick: $.handleToggleClick,
|
|
98
|
+
children: F && V !== void 0 && !v ? /* @__PURE__ */ f("button", {
|
|
99
|
+
type: "button",
|
|
100
|
+
className: e.uiClearButton,
|
|
101
|
+
"data-ui": "select-clear-button",
|
|
102
|
+
"data-action": "clear-select",
|
|
103
|
+
onMouseDown: (e) => {
|
|
104
|
+
e.preventDefault(), e.stopPropagation();
|
|
105
|
+
},
|
|
106
|
+
onClick: (e) => {
|
|
107
|
+
e.preventDefault(), e.stopPropagation(), Ie();
|
|
108
|
+
},
|
|
109
|
+
"aria-label": "Очистить выбор",
|
|
110
|
+
children: /* @__PURE__ */ f(ie, {})
|
|
111
|
+
}) : null
|
|
112
|
+
}),
|
|
113
|
+
onChange: (e) => {
|
|
114
|
+
k && $.handleTriggerInputChange(e.target.value);
|
|
115
|
+
},
|
|
116
|
+
onClick: $.handleTriggerClick,
|
|
117
|
+
onFocus: (e) => {
|
|
118
|
+
$.handleTriggerFocus(e.currentTarget);
|
|
119
|
+
},
|
|
120
|
+
onKeyDown: (e) => {
|
|
121
|
+
ke(e), !e.defaultPrevented && $.handleTriggerKeyDown({
|
|
122
|
+
event: e,
|
|
123
|
+
onActivateWhenOpen: Oe,
|
|
124
|
+
enableSpaceActivation: !k
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}), /* @__PURE__ */ f(r, {
|
|
128
|
+
open: R,
|
|
129
|
+
context: ye,
|
|
130
|
+
floatingStyles: be,
|
|
131
|
+
listId: s,
|
|
132
|
+
labelId: i,
|
|
133
|
+
descriptionId: a,
|
|
134
|
+
activeOptionId: q ? K(s) : void 0,
|
|
135
|
+
setFloating: Ce,
|
|
136
|
+
getFloatingProps: xe,
|
|
137
|
+
onKeyDown: Ae,
|
|
138
|
+
className: u(e.uiPopupOptions, de),
|
|
139
|
+
header: A,
|
|
140
|
+
children: /* @__PURE__ */ f("div", {
|
|
141
|
+
className: u(fe, "h100 scrollable"),
|
|
142
|
+
children: q ? W.map((t, n) => {
|
|
143
|
+
let r = C(t), i = B !== void 0 && r === B, a = n === ve, o = E?.(t) ?? !1, c = {
|
|
144
|
+
active: a,
|
|
145
|
+
selected: i,
|
|
146
|
+
disabled: o
|
|
147
|
+
};
|
|
148
|
+
return /* @__PURE__ */ f("div", {
|
|
149
|
+
id: je(s, n),
|
|
150
|
+
ref: (e) => we(n, e),
|
|
151
|
+
role: "option",
|
|
152
|
+
"aria-selected": i,
|
|
153
|
+
"aria-disabled": o || void 0,
|
|
154
|
+
"aria-label": se?.(t),
|
|
155
|
+
className: u(e.uiPopupOption, o && e.disabled, a && e.uiPopupOptionActive, i && e.selected, ce?.(t, c)),
|
|
156
|
+
onClick: () => De(t),
|
|
157
|
+
children: D ? D(t, c) : /* @__PURE__ */ p(d, { children: [
|
|
158
|
+
f(i ? re : "span", { className: e.uiPopupOptionIcon }),
|
|
159
|
+
/* @__PURE__ */ f("div", {
|
|
160
|
+
className: e.uiOptionText,
|
|
161
|
+
children: w(t)
|
|
162
|
+
}),
|
|
163
|
+
T && /* @__PURE__ */ f("div", {
|
|
164
|
+
className: e.uiOptionCode,
|
|
165
|
+
children: T(t)
|
|
166
|
+
})
|
|
167
|
+
] })
|
|
168
|
+
}, r);
|
|
169
|
+
}) : /* @__PURE__ */ f(te, {
|
|
170
|
+
emptyState: j,
|
|
171
|
+
loadingState: M,
|
|
172
|
+
errorState: N
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
})] });
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { h as n, _ as t };
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=Select-BJ5OqTe7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select-BJ5OqTe7.js","names":[],"sources":["../../src/select/lib/getOptionSearchText.ts","../../src/select/Select.module.scss","../../src/select/Select.tsx"],"sourcesContent":["import { ReactNode } from \"react\";\n\nimport { InputType } from \"@ryuzaki13/react-foundation-lib/types\";\n\nimport { extractPickerTextContent } from \"../../picker\";\n\nexport function getOptionSearchText<T extends InputType>({\n\toption,\n\tgetOptionLabel,\n\tgetOptionCode\n}: {\n\toption: T;\n\tgetOptionLabel: (option: T) => ReactNode;\n\tgetOptionCode?: (option: T) => ReactNode;\n}) {\n\treturn [extractPickerTextContent(getOptionLabel(option)), extractPickerTextContent(getOptionCode?.(option))]\n\t\t.filter((part): part is string => Boolean(part))\n\t\t.join(\" \")\n\t\t.toLowerCase();\n}\n\n/** Находит selected option по value и возвращает fallback, если значение еще не нормализовано. */\nexport function resolveSelectedOption<TOption extends { value: string }>(\n\toptions: readonly TOption[],\n\tvalue: string,\n\tfallback: TOption\n): TOption {\n\treturn options.find((option) => option.value === value) ?? fallback;\n}\n",".inputWithOverlay {\n\tcolor: transparent;\n\tcaret-color: transparent;\n}\n\n.valueOverlay {\n\tposition: absolute;\n\tinset: 0 calc(var(--control-height) + var(--space-xs)) 0 var(--space-md);\n\tdisplay: flex;\n\talign-items: center;\n\tpointer-events: none;\n\toverflow: hidden;\n}\n","import { ReactNode, useRef, useState } from \"react\";\n\nimport { Placement } from \"@floating-ui/react\";\nimport { InputType } from \"@ryuzaki13/react-foundation-lib/types\";\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { CheckIcon, XIcon } from \"lucide-react\";\n\nimport {\n\textractPickerTextContent,\n\tPickerField,\n\tPickerPopup,\n\tPickerStatus,\n\tPickerTriggerActions,\n\tPickerTriggerInput,\n\tusePickerDefaultFilter,\n\tusePickerFloatingListbox,\n\tusePickerQuery,\n\tusePickerTriggerController\n} from \"../picker\";\nimport { ChangeHandler, UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport { getOptionSearchText } from \"./lib\";\nimport styles from \"./Select.module.scss\";\n\nexport type SelectOptionKey = string | number;\n\nexport type SelectOptionState = {\n\tactive: boolean;\n\tselected: boolean;\n\tdisabled: boolean;\n};\n\ntype SelectSharedProps<TOption extends InputType> = Omit<UiBaseProps<TOption, TOption | undefined>, \"onChange\"> & {\n\toptions: readonly TOption[];\n\tgetOptionKey: (option: TOption) => SelectOptionKey;\n\tgetOptionLabel: (option: TOption) => ReactNode;\n\tgetOptionCode?: (option: TOption) => ReactNode;\n\tgetOptionDisabled?: (option: TOption) => boolean;\n\tgetOptionAriaLabel?: (option: TOption) => string;\n\tgetOptionClassName?: (option: TOption, state: SelectOptionState) => string | undefined;\n\trenderOption?: (option: TOption, state: SelectOptionState) => ReactNode;\n\trenderValue?: (option: TOption) => ReactNode;\n\tclassName?: string;\n\tbuttonClassName?: string;\n\toptionsClassName?: string;\n\toptionsContentClassName?: string;\n\tsearchable?: boolean;\n\tquery?: string;\n\tdefaultQuery?: string;\n\tonQuery?: (value: string) => void;\n\tdefaultFilter?: boolean;\n\trenderPopupHeader?: ReactNode;\n\temptyState?: ReactNode;\n\tloadingState?: ReactNode;\n\terrorState?: ReactNode;\n\tplacement?: Placement;\n};\n\ntype SelectChangeValue<TOption extends InputType, TClearable extends boolean | undefined> = true extends TClearable\n\t? TOption | undefined\n\t: TOption;\n\nexport type SelectProps<TOption extends InputType, TClearable extends boolean | undefined = false> = SelectSharedProps<TOption> & {\n\tclearable?: TClearable;\n\tonChange: ChangeHandler<SelectChangeValue<TOption, TClearable>>;\n};\n\n/**\n * Выпадающий список выбора значения из набора опций. Подходит для форм, фильтров и простых справочников.\n */\nexport function Select<TOption extends InputType, TClearable extends boolean | undefined = false>(props: SelectProps<TOption, TClearable>) {\n\tconst {\n\t\tlabel,\n\t\tdescription,\n\t\tdisabled,\n\t\tplaceholder,\n\t\tsize,\n\t\toptions,\n\t\tvalue,\n\t\tonChange,\n\t\tgetOptionKey,\n\t\tgetOptionLabel,\n\t\tgetOptionCode,\n\t\tgetOptionDisabled,\n\t\tgetOptionAriaLabel,\n\t\tgetOptionClassName,\n\t\trenderOption,\n\t\trenderValue,\n\t\tclassName,\n\t\tbuttonClassName,\n\t\toptionsClassName,\n\t\toptionsContentClassName,\n\t\tsearchable = false,\n\t\tdefaultFilter = true,\n\t\tquery,\n\t\tdefaultQuery,\n\t\tonQuery,\n\t\trenderPopupHeader,\n\t\temptyState,\n\t\tloadingState,\n\t\terrorState,\n\t\tplacement = \"bottom-start\",\n\t\tclearable = false\n\t} = props;\n\tconst emitChange = onChange as ChangeHandler<TOption | undefined>;\n\n\tconst inputRef = useRef<HTMLInputElement | null>(null);\n\tconst [open, setOpen] = useState(false);\n\tconst triggerMode = searchable ? \"search-single\" : \"display\";\n\tconst selectedKey = value === undefined ? undefined : getOptionKey(value);\n\tconst selectedOption =\n\t\tselectedKey === undefined ? undefined : (options.find((option) => getOptionKey(option) === selectedKey) ?? value);\n\tconst { query: currentQuery, setQuery } = usePickerQuery({\n\t\topen,\n\t\tquery,\n\t\tdefaultQuery,\n\t\tonQuery,\n\t\ttriggerMode\n\t});\n\tconst visibleOptions = usePickerDefaultFilter({\n\t\toptions,\n\t\tquery: currentQuery,\n\t\tenabled: searchable && defaultFilter,\n\t\tgetSearchText: (option) =>\n\t\t\tgetOptionSearchText({\n\t\t\t\toption,\n\t\t\t\tgetOptionLabel,\n\t\t\t\tgetOptionCode\n\t\t\t})\n\t});\n\tconst selectedIndex = selectedKey === undefined ? -1 : visibleOptions.findIndex((option) => getOptionKey(option) === selectedKey);\n\tconst {\n\t\tactiveIndex,\n\t\tcontext,\n\t\tfloatingStyles,\n\t\tgetFloatingProps,\n\t\tsetReference,\n\t\tsetFloating,\n\t\tsetOptionRef,\n\t\tclose,\n\t\topenList,\n\t\ttoggleOpen,\n\t\tselectOption,\n\t\tselectActiveOption,\n\t\thandleReferenceKeyDown,\n\t\thandleFloatingKeyDown,\n\t\tgetOptionId,\n\t\tgetActiveOptionId\n\t} = usePickerFloatingListbox({\n\t\toptions: visibleOptions,\n\t\tselectedIndex,\n\t\topen,\n\t\tonOpenChange: setOpen,\n\t\tgetOptionDisabled,\n\t\tonSelect: emitChange,\n\t\tdisabled,\n\t\tplacement,\n\t\ttriggerMode\n\t});\n\n\tconst hasOptions = visibleOptions.length > 0;\n\tconst labelContent = selectedOption !== undefined ? getOptionLabel(selectedOption) : undefined;\n\tconst displayContent = selectedOption !== undefined ? (renderValue ? renderValue(selectedOption) : labelContent) : undefined;\n\tconst labelText = extractPickerTextContent(labelContent);\n\tconst codeText = selectedOption !== undefined ? extractPickerTextContent(getOptionCode?.(selectedOption)) : undefined;\n\tconst displayText =\n\t\textractPickerTextContent(displayContent) ?? labelText ?? codeText ?? (selectedKey !== undefined ? String(selectedKey) : \"\");\n\tconst showSearchValue = searchable && (open || currentQuery.length > 0);\n\tconst inputValue = showSearchValue ? currentQuery : selectedOption !== undefined ? displayText : \"\";\n\tconst showDisplayOverlay =\n\t\tselectedOption !== undefined &&\n\t\tdisplayContent !== undefined &&\n\t\textractPickerTextContent(displayContent) === undefined &&\n\t\t!showSearchValue;\n\tconst triggerController = usePickerTriggerController({\n\t\tmode: triggerMode,\n\t\topen,\n\t\tcurrentQuery,\n\t\thasDisplayValue: selectedOption !== undefined,\n\t\tinputRef,\n\t\tsetQuery,\n\t\topenList,\n\t\tclose,\n\t\ttoggleOpen\n\t});\n\tconst setInputNode = (node: HTMLInputElement | null) => {\n\t\tinputRef.current = node;\n\t};\n\tconst handleClear = () => {\n\t\tif (clearable) {\n\t\t\temitChange(undefined);\n\t\t}\n\n\t\tsetQuery(\"\");\n\t\tclose();\n\t};\n\n\treturn (\n\t\t<PickerField\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tplaceholder={placeholder}\n\t\t\tsize={size}\n\t\t\tclassName={className}>\n\t\t\t{({ controlId, labelId, describedBy }) => {\n\t\t\t\tconst listId = `${controlId}-listbox`;\n\n\t\t\t\treturn (\n\t\t\t\t\t<>\n\t\t\t\t\t\t<PickerTriggerInput\n\t\t\t\t\t\t\tref={setInputNode}\n\t\t\t\t\t\t\trootRef={setReference}\n\t\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\treadOnly={!searchable}\n\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\trole=\"combobox\"\n\t\t\t\t\t\t\tvalue={inputValue}\n\t\t\t\t\t\t\tplaceholder={selectedOption === undefined || showSearchValue ? placeholder : undefined}\n\t\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t\t\t\t\taria-expanded={open}\n\t\t\t\t\t\t\taria-controls={open ? listId : undefined}\n\t\t\t\t\t\t\taria-autocomplete={searchable ? \"list\" : \"none\"}\n\t\t\t\t\t\t\taria-activedescendant={open ? getActiveOptionId(listId) : undefined}\n\t\t\t\t\t\t\tinputClassName={cn(showDisplayOverlay && styles.inputWithOverlay, buttonClassName, \"textOverflow\")}\n\t\t\t\t\t\t\toverlay={showDisplayOverlay ? <div className={styles.valueOverlay}>{displayContent}</div> : undefined}\n\t\t\t\t\t\t\tendAdornment={\n\t\t\t\t\t\t\t\t<PickerTriggerActions\n\t\t\t\t\t\t\t\t\topen={open}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\tonToggleMouseDown={triggerController.handleToggleMouseDown}\n\t\t\t\t\t\t\t\t\tonToggleClick={triggerController.handleToggleClick}>\n\t\t\t\t\t\t\t\t\t{clearable && selectedOption !== undefined && !disabled ? (\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\t\tclassName={uiStyles.uiClearButton}\n\t\t\t\t\t\t\t\t\t\t\tdata-ui=\"select-clear-button\"\n\t\t\t\t\t\t\t\t\t\t\tdata-action=\"clear-select\"\n\t\t\t\t\t\t\t\t\t\t\tonMouseDown={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t\t\t\t\t\thandleClear();\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\taria-label=\"Очистить выбор\">\n\t\t\t\t\t\t\t\t\t\t\t<XIcon />\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t</PickerTriggerActions>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\t\tif (!searchable) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttriggerController.handleTriggerInputChange(event.target.value);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={triggerController.handleTriggerClick}\n\t\t\t\t\t\t\tonFocus={(event) => {\n\t\t\t\t\t\t\t\ttriggerController.handleTriggerFocus(event.currentTarget);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\t\thandleReferenceKeyDown(event);\n\n\t\t\t\t\t\t\t\tif (event.defaultPrevented) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\ttriggerController.handleTriggerKeyDown({\n\t\t\t\t\t\t\t\t\tevent,\n\t\t\t\t\t\t\t\t\tonActivateWhenOpen: selectActiveOption,\n\t\t\t\t\t\t\t\t\tenableSpaceActivation: !searchable\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<PickerPopup\n\t\t\t\t\t\t\topen={open}\n\t\t\t\t\t\t\tcontext={context}\n\t\t\t\t\t\t\tfloatingStyles={floatingStyles}\n\t\t\t\t\t\t\tlistId={listId}\n\t\t\t\t\t\t\tlabelId={labelId}\n\t\t\t\t\t\t\tdescriptionId={describedBy}\n\t\t\t\t\t\t\tactiveOptionId={hasOptions ? getActiveOptionId(listId) : undefined}\n\t\t\t\t\t\t\tsetFloating={setFloating}\n\t\t\t\t\t\t\tgetFloatingProps={getFloatingProps}\n\t\t\t\t\t\t\tonKeyDown={handleFloatingKeyDown}\n\t\t\t\t\t\t\tclassName={cn(uiStyles.uiPopupOptions, optionsClassName)}\n\t\t\t\t\t\t\theader={renderPopupHeader}>\n\t\t\t\t\t\t\t<div className={cn(optionsContentClassName, \"h100 scrollable\")}>\n\t\t\t\t\t\t\t\t{hasOptions ? (\n\t\t\t\t\t\t\t\t\tvisibleOptions.map((option, index) => {\n\t\t\t\t\t\t\t\t\t\tconst optionKey = getOptionKey(option);\n\t\t\t\t\t\t\t\t\t\tconst selected = selectedKey !== undefined && optionKey === selectedKey;\n\t\t\t\t\t\t\t\t\t\tconst active = index === activeIndex;\n\t\t\t\t\t\t\t\t\t\tconst optionDisabled = getOptionDisabled?.(option) ?? false;\n\t\t\t\t\t\t\t\t\t\tconst optionState = { active, selected, disabled: optionDisabled };\n\n\t\t\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\t\t\tkey={optionKey}\n\t\t\t\t\t\t\t\t\t\t\t\tid={getOptionId(listId, index)}\n\t\t\t\t\t\t\t\t\t\t\t\tref={(node) => setOptionRef(index, node)}\n\t\t\t\t\t\t\t\t\t\t\t\trole=\"option\"\n\t\t\t\t\t\t\t\t\t\t\t\taria-selected={selected}\n\t\t\t\t\t\t\t\t\t\t\t\taria-disabled={optionDisabled || undefined}\n\t\t\t\t\t\t\t\t\t\t\t\taria-label={getOptionAriaLabel?.(option)}\n\t\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t\tuiStyles.uiPopupOption,\n\t\t\t\t\t\t\t\t\t\t\t\t\toptionDisabled && uiStyles.disabled,\n\t\t\t\t\t\t\t\t\t\t\t\t\tactive && uiStyles.uiPopupOptionActive,\n\t\t\t\t\t\t\t\t\t\t\t\t\tselected && uiStyles.selected,\n\t\t\t\t\t\t\t\t\t\t\t\t\tgetOptionClassName?.(option, optionState)\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => selectOption(option)}>\n\t\t\t\t\t\t\t\t\t\t\t\t{renderOption ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\trenderOption(option, optionState)\n\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{selected ? (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<CheckIcon className={uiStyles.uiPopupOptionIcon} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span className={uiStyles.uiPopupOptionIcon} />\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className={uiStyles.uiOptionText}>{getOptionLabel(option)}</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{getOptionCode && (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<div className={uiStyles.uiOptionCode}>{getOptionCode(option)}</div>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<PickerStatus emptyState={emptyState} loadingState={loadingState} errorState={errorState} />\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</PickerPopup>\n\t\t\t\t\t</>\n\t\t\t\t);\n\t\t\t}}\n\t\t</PickerField>\n\t);\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./Select-
|
|
1
|
+
import { t as e } from "./Select-BJ5OqTe7.js";
|
|
2
2
|
import { jsx as t } from "react/jsx-runtime";
|
|
3
3
|
//#region src/select/SerializableSelect.tsx
|
|
4
4
|
function n(e, t) {
|
|
@@ -30,4 +30,4 @@ function i({ label: i, description: a, disabled: o, placeholder: s, size: c, opt
|
|
|
30
30
|
//#endregion
|
|
31
31
|
export { i as t };
|
|
32
32
|
|
|
33
|
-
//# sourceMappingURL=SerializableSelect-
|
|
33
|
+
//# sourceMappingURL=SerializableSelect-CNe728Qa.js.map
|
package/dist/chunks/{SerializableSelect-DkYeJtAO.js.map → SerializableSelect-CNe728Qa.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SerializableSelect-
|
|
1
|
+
{"version":3,"file":"SerializableSelect-CNe728Qa.js","names":[],"sources":["../../src/select/SerializableSelect.tsx"],"sourcesContent":["import { Select } from \"./Select\";\n\nimport type { UiBaseProps } from \"../types\";\nimport type { SelectOptionKey } from \"./Select\";\n\ntype SerializableOptionRecord = Record<string, unknown>;\n\ntype SerializableOptionKeyField<TOption extends SerializableOptionRecord> = {\n\t[K in keyof TOption]: Extract<TOption[K], SelectOptionKey> extends never ? never : K;\n}[keyof TOption];\n\ntype SerializableOptionValue<TOption extends SerializableOptionRecord, TOptionKey extends SerializableOptionKeyField<TOption>> = Extract<\n\tTOption[TOptionKey],\n\tSelectOptionKey\n>;\n\nexport interface SerializableSelectProps<\n\tTOption extends SerializableOptionRecord,\n\tTOptionKey extends SerializableOptionKeyField<TOption>,\n\tTOptionLabel extends keyof TOption\n> extends Omit<UiBaseProps<SerializableOptionValue<TOption, TOptionKey> | undefined>, \"onChange\"> {\n\toptions: readonly TOption[];\n\tonChange: (value: SerializableOptionValue<TOption, TOptionKey> | undefined) => void;\n\toptionKey: TOptionKey;\n\toptionLabel: TOptionLabel;\n\trenderCode?: true;\n\tclassName?: string;\n\tclearable?: boolean;\n}\n\nfunction getSerializableOptionKey<TOption extends SerializableOptionRecord, TOptionKey extends SerializableOptionKeyField<TOption>>(\n\toption: TOption,\n\toptionKey: TOptionKey\n): Extract<TOption[TOptionKey], SelectOptionKey> {\n\treturn option[optionKey] as Extract<TOption[TOptionKey], SelectOptionKey>;\n}\n\nfunction getSerializableOptionLabel<\n\tTOption extends SerializableOptionRecord,\n\tTOptionKey extends SerializableOptionKeyField<TOption>,\n\tTOptionLabel extends keyof TOption\n>(option: TOption, optionLabel: TOptionLabel, optionKey: TOptionKey): string | number {\n\tconst label = option[optionLabel];\n\n\tif (typeof label === \"string\" || typeof label === \"number\") {\n\t\treturn label;\n\t}\n\n\tconst key = getSerializableOptionKey(option, optionKey);\n\treturn typeof key === \"string\" || typeof key === \"number\" ? key : String(key);\n}\n\nexport function SerializableSelect<\n\tTOption extends SerializableOptionRecord,\n\tTOptionKey extends SerializableOptionKeyField<TOption>,\n\tTOptionLabel extends keyof TOption\n>({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tplaceholder,\n\tsize,\n\toptions,\n\tvalue,\n\tonChange,\n\toptionKey,\n\toptionLabel,\n\trenderCode,\n\tclassName,\n\tclearable\n}: SerializableSelectProps<TOption, TOptionKey, TOptionLabel>) {\n\tconst selectedOption =\n\t\tvalue === undefined ? undefined : options.find((option) => getSerializableOptionKey(option, optionKey) === value);\n\n\treturn (\n\t\t<Select\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tplaceholder={placeholder}\n\t\t\tsize={size}\n\t\t\toptions={options}\n\t\t\tvalue={selectedOption}\n\t\t\tonChange={(option: TOption | undefined) => onChange(option ? getSerializableOptionKey(option, optionKey) : undefined)}\n\t\t\tgetOptionKey={(option: TOption) => getSerializableOptionKey(option, optionKey)}\n\t\t\tgetOptionLabel={(option: TOption) => getSerializableOptionLabel(option, optionLabel, optionKey)}\n\t\t\tgetOptionCode={renderCode ? (option: TOption) => getSerializableOptionKey(option, optionKey) : undefined}\n\t\t\tclassName={className}\n\t\t\tclearable={clearable}\n\t\t/>\n\t);\n}\n"],"mappings":";;;AA8BA,SAAS,EACR,GACA,GACgD;CAChD,OAAO,EAAO;AACf;AAEA,SAAS,EAIP,GAAiB,GAA2B,GAAwC;CACrF,IAAM,IAAQ,EAAO;CAErB,IAAI,OAAO,KAAU,YAAY,OAAO,KAAU,UACjD,OAAO;CAGR,IAAM,IAAM,EAAyB,GAAQ,CAAS;CACtD,OAAO,OAAO,KAAQ,YAAY,OAAO,KAAQ,WAAW,IAAM,OAAO,CAAG;AAC7E;AAEA,SAAgB,EAId,EACD,UACA,gBACA,aACA,gBACA,SACA,YACA,UACA,aACA,cACA,gBACA,eACA,cACA,gBAC8D;CAI9D,OACC,kBAAC,GAAD;EACQ;EACM;EACH;EACG;EACP;EACG;EACT,OAVD,MAAU,KAAA,IAAY,KAAA,IAAY,EAAQ,MAAM,MAAW,EAAyB,GAAQ,CAAS,MAAM,CAAK;EAW/G,WAAW,MAAgC,EAAS,IAAS,EAAyB,GAAQ,CAAS,IAAI,KAAA,CAAS;EACpH,eAAe,MAAoB,EAAyB,GAAQ,CAAS;EAC7E,iBAAiB,MAAoB,EAA2B,GAAQ,GAAa,CAAS;EAC9F,eAAe,KAAc,MAAoB,EAAyB,GAAQ,CAAS,IAAI,KAAA;EACpF;EACA;CACX,CAAA;AAEH"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e } from "./Select-
|
|
1
|
+
import { t as e } from "./Select-BJ5OqTe7.js";
|
|
2
2
|
import { useMemo as t } from "react";
|
|
3
3
|
import { cn as n } from "@ryuzaki13/react-foundation-lib/utils";
|
|
4
4
|
import { DEFAULT_VALUE_STATES as r, VALUE_STATE_COLOR_TOKENS as i } from "@ryuzaki13/react-foundation-lib/formatters";
|
|
@@ -75,4 +75,4 @@ function m({ label: i, description: m, disabled: h, placeholder: g, size: _, val
|
|
|
75
75
|
//#endregion
|
|
76
76
|
export { m as t };
|
|
77
77
|
|
|
78
|
-
//# sourceMappingURL=StateSelect-
|
|
78
|
+
//# sourceMappingURL=StateSelect-ujAre258.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateSelect-
|
|
1
|
+
{"version":3,"file":"StateSelect-ujAre258.js","names":[],"sources":["../../src/state-select/StateSelect.module.scss","../../src/state-select/StateSelect.tsx"],"sourcesContent":[".button {\n\tpadding-left: var(--space-sm);\n}\n\n.valueContainer {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-sm);\n\twidth: 100%;\n\tmin-height: 1.5em;\n\tmin-width: 0;\n}\n\n.swatch {\n\t--state-color: transparent;\n\n\twidth: 1.25em;\n\theight: 1.25em;\n\tflex-shrink: 0;\n\tdisplay: inline-block;\n\tborder-radius: var(--radius-xs);\n\tborder: var(--border-width) solid var(--border-0);\n\tbackground-color: var(--state-color);\n\n\t&[data-empty] {\n\t\tbackground-color: var(--surface-0);\n\t\tbackground-image: repeating-linear-gradient(135deg, var(--border-0), var(--border-0) 0.25em, transparent 0.25em, transparent 0.5em);\n\t}\n}\n\n// .options {\n// \tpadding: var(--space-xs);\n// }\n\n.optionsPalette {\n\t--input-width: auto;\n\n\tdisplay: grid;\n\tgrid-template-columns: repeat(5, minmax(0, 1fr));\n\tgap: var(--space-xs);\n}\n\n.optionsDetailed {\n\t--input-width: 16em;\n}\n\n.option {\n\tborder-radius: var(--radius-sm);\n\toutline: none;\n\tuser-select: none;\n}\n\n.optionPalette {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tpadding: var(--space-sm);\n\tmin-width: 2.25em;\n}\n\n.optionDetailed {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-sm);\n\tpadding: var(--space-xs) var(--space-sm);\n}\n\n.optionMeta {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n\tmin-width: 0;\n}\n\n.optionMetaIcon {\n\tdisplay: inline-flex;\n\talign-items: center;\n}\n\n.optionMetaLabel {\n\tmin-width: 0;\n\twhite-space: nowrap;\n\ttext-overflow: ellipsis;\n\toverflow: hidden;\n}\n","import { CSSProperties, ReactNode, useMemo } from \"react\";\n\nimport { DEFAULT_VALUE_STATES, VALUE_STATE_COLOR_TOKENS } from \"@ryuzaki13/react-foundation-lib/formatters\";\nimport { State } from \"@ryuzaki13/react-foundation-lib/types\";\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { Select, SelectProps } from \"../select\";\nimport { UiBaseProps } from \"../types\";\n\nimport styles from \"./StateSelect.module.scss\";\n\nexport type StateMeta = {\n\tlabel?: ReactNode;\n\ticon?: ReactNode;\n};\n\nexport interface StateSelectProps extends Omit<UiBaseProps<State | undefined>, \"placeholder\"> {\n\tplaceholder?: string;\n\toptions?: readonly State[];\n\tstateMeta?: Partial<Record<State, StateMeta>>;\n\tclassName?: string;\n\tclearable?: boolean;\n}\n\ninterface StateSwatchProps {\n\tstate: State;\n\tclassName?: string;\n}\n\nfunction StateSwatch({ state, className }: StateSwatchProps) {\n\treturn (\n\t\t<span\n\t\t\tclassName={cn(styles.swatch, className)}\n\t\t\tdata-empty={state === \"none\" ? \"\" : undefined}\n\t\t\tstyle={{ \"--state-color\": VALUE_STATE_COLOR_TOKENS[state] } as CSSProperties}\n\t\t/>\n\t);\n}\n\nfunction hasStateMeta(meta: StateMeta | undefined): boolean {\n\treturn Boolean(meta?.icon || meta?.label);\n}\n\nfunction resolveStateAriaLabel(state: State, meta: StateMeta | undefined): string {\n\tif (typeof meta?.label === \"string\" && meta.label.trim()) {\n\t\treturn meta.label;\n\t}\n\n\treturn state || \"empty\";\n}\n\nfunction renderStateMeta(meta: StateMeta | undefined) {\n\tif (!hasStateMeta(meta)) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<span className={styles.optionMeta}>\n\t\t\t{meta?.icon ? <span className={styles.optionMetaIcon}>{meta.icon}</span> : null}\n\t\t\t{meta?.label ? <span className={styles.optionMetaLabel}>{meta.label}</span> : null}\n\t\t</span>\n\t);\n}\n\nfunction renderStateValue(state: State, meta: StateMeta | undefined) {\n\treturn (\n\t\t<div className={styles.valueContainer}>\n\t\t\t<StateSwatch state={state} />\n\t\t\t{renderStateMeta(meta)}\n\t\t</div>\n\t);\n}\n\n/**\n * Специализированный селект для выбора цветового или статусного состояния. Используется там, где значению соответствует визуальный swatch.\n */\nexport function StateSelect({\n\tlabel,\n\tdescription,\n\tdisabled,\n\tplaceholder,\n\tsize,\n\tvalue,\n\tonChange,\n\toptions = DEFAULT_VALUE_STATES,\n\tstateMeta,\n\tclassName,\n\tclearable\n}: StateSelectProps) {\n\tconst stateOptions = useMemo(() => Array.from(new Set(options)), [options]);\n\tconst hasDetailedOptions = stateOptions.some((stateOption) => hasStateMeta(stateMeta?.[stateOption]));\n\n\tconst sharedSelectProps: Pick<\n\t\tSelectProps<State>,\n\t\t| \"getOptionKey\"\n\t\t| \"getOptionLabel\"\n\t\t| \"getOptionAriaLabel\"\n\t\t| \"renderValue\"\n\t\t| \"renderOption\"\n\t\t| \"buttonClassName\"\n\t\t| \"optionsContentClassName\"\n\t\t| \"getOptionClassName\"\n\t> = {\n\t\tgetOptionKey: (stateOption) => stateOption || \"__empty_state__\",\n\t\tgetOptionLabel: (stateOption) => stateMeta?.[stateOption]?.label ?? stateOption,\n\t\tgetOptionAriaLabel: (stateOption) => resolveStateAriaLabel(stateOption, stateMeta?.[stateOption]),\n\t\trenderValue: (stateOption) => renderStateValue(stateOption, stateMeta?.[stateOption]),\n\t\trenderOption: (stateOption) => (\n\t\t\t<>\n\t\t\t\t<StateSwatch state={stateOption} />\n\t\t\t\t{hasDetailedOptions ? renderStateMeta(stateMeta?.[stateOption]) : null}\n\t\t\t</>\n\t\t),\n\t\tbuttonClassName: styles.button,\n\t\toptionsContentClassName: cn(/*styles.options,*/ hasDetailedOptions ? styles.optionsDetailed : styles.optionsPalette),\n\t\tgetOptionClassName: () => cn(styles.option, hasDetailedOptions ? styles.optionDetailed : styles.optionPalette)\n\t};\n\n\treturn (\n\t\t<Select\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tplaceholder={placeholder}\n\t\t\tsize={size}\n\t\t\tvalue={value}\n\t\t\tonChange={onChange}\n\t\t\toptions={stateOptions}\n\t\t\tclassName={className}\n\t\t\tclearable={clearable}\n\t\t\t{...sharedSelectProps}\n\t\t/>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AC6BA,SAAS,EAAY,EAAE,UAAO,gBAA+B;CAC5D,OACC,kBAAC,QAAD;EACC,WAAW,EAAG,EAAO,QAAQ,CAAS;EACtC,cAAY,MAAU,SAAS,KAAK,KAAA;EACpC,OAAO,EAAE,iBAAiB,EAAyB,GAAO;CAC1D,CAAA;AAEH;AAEA,SAAS,EAAa,GAAsC;CAC3D,OAAO,GAAQ,GAAM,QAAQ,GAAM;AACpC;AAEA,SAAS,EAAsB,GAAc,GAAqC;CAKjF,OAJI,OAAO,GAAM,SAAU,YAAY,EAAK,MAAM,KAAK,IAC/C,EAAK,QAGN,KAAS;AACjB;AAEA,SAAS,EAAgB,GAA6B;CAKrD,OAJK,EAAa,CAAI,IAKrB,kBAAC,QAAD;EAAM,WAAW,EAAO;YAAxB,CACE,GAAM,OAAO,kBAAC,QAAD;GAAM,WAAW,EAAO;aAAiB,EAAK;EAAW,CAAA,IAAI,MAC1E,GAAM,QAAQ,kBAAC,QAAD;GAAM,WAAW,EAAO;aAAkB,EAAK;EAAY,CAAA,IAAI,IACzE;MAPC;AAST;AAEA,SAAS,EAAiB,GAAc,GAA6B;CACpE,OACC,kBAAC,OAAD;EAAK,WAAW,EAAO;YAAvB,CACC,kBAAC,GAAD,EAAoB,SAAQ,CAAA,GAC3B,EAAgB,CAAI,CACjB;;AAEP;AAKA,SAAgB,EAAY,EAC3B,UACA,gBACA,aACA,gBACA,SACA,UACA,aACA,aAAU,GACV,cACA,cACA,gBACoB;CACpB,IAAM,IAAe,QAAc,MAAM,KAAK,IAAI,IAAI,CAAO,CAAC,GAAG,CAAC,CAAO,CAAC,GACpE,IAAqB,EAAa,MAAM,MAAgB,EAAa,IAAY,EAAY,CAAC;CA4BpG,OACC,kBAAC,GAAD;EACQ;EACM;EACH;EACG;EACP;EACC;EACG;EACV,SAAS;EACE;EACA;EA1BZ,eAAe,MAAgB,KAAe;EAC9C,iBAAiB,MAAgB,IAAY,EAAY,EAAE,SAAS;EACpE,qBAAqB,MAAgB,EAAsB,GAAa,IAAY,EAAY;EAChG,cAAc,MAAgB,EAAiB,GAAa,IAAY,EAAY;EACpF,eAAe,MACd,kBAAA,GAAA,EAAA,UAAA,CACC,kBAAC,GAAD,EAAa,OAAO,EAAc,CAAA,GACjC,IAAqB,EAAgB,IAAY,EAAY,IAAI,IACjE,EAAA,CAAA;EAEH,iBAAiB,EAAO;EACxB,yBAAyB,EAAuB,IAAqB,EAAO,kBAAkB,EAAO,cAAc;EACnH,0BAA0B,EAAG,EAAO,QAAQ,IAAqB,EAAO,iBAAiB,EAAO,aAAa;CAgB5G,CAAA;AAEH"}
|
|
@@ -2,7 +2,7 @@ import { a as e } from "./odata-DSW7z3nh.js";
|
|
|
2
2
|
import { s as t } from "./Input-BmjlpA09.js";
|
|
3
3
|
import { t as n } from "./SelectOptionContent-CI7wq9Oi.js";
|
|
4
4
|
import { n as r } from "./useODataSelectBase-BbeKdq6x.js";
|
|
5
|
-
import { t as i } from "./Select-
|
|
5
|
+
import { t as i } from "./Select-BJ5OqTe7.js";
|
|
6
6
|
import { useMemo as a } from "react";
|
|
7
7
|
import { jsx as o } from "react/jsx-runtime";
|
|
8
8
|
//#region src/select/model/useODataSelect.ts
|
|
@@ -78,4 +78,4 @@ var l = ({ odata: r, segment: a, model: l, size: u, label: d, description: f, di
|
|
|
78
78
|
//#endregion
|
|
79
79
|
export { l as t };
|
|
80
80
|
|
|
81
|
-
//# sourceMappingURL=select-
|
|
81
|
+
//# sourceMappingURL=select-BkLc6dyx.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select-BkLc6dyx.js","names":[],"sources":["../../src/select/model/useODataSelect.ts","../../src/select/ODataSelect.tsx"],"sourcesContent":["import { useMemo } from \"react\";\n\nimport { ODataCollectionModel, ODataSingleSelectProps } from \"@ryuzaki13/react-foundation-api/odata\";\nimport { CollectionItem } from \"@ryuzaki13/react-foundation-lib/odata\";\n\nimport { useODataSelectBase } from \"./useODataSelectBase\";\n\ninterface UseODataSelectOptions extends Omit<ODataSingleSelectProps, \"model\"> {\n\tmodel: Required<ODataCollectionModel>;\n\tonChange: (value: string | undefined) => void;\n}\n\nexport function useODataSelect({ odata, segment, model, value, dependencies, onChange }: UseODataSelectOptions) {\n\tconst odataModel = useODataSelectBase({\n\t\todata,\n\t\tsegment,\n\t\tmodel,\n\t\tvalue: value ? [value] : [],\n\t\tdependencies\n\t});\n\n\tconst selectedItem = odataModel.selectedItems[0];\n\tconst options = useMemo(() => {\n\t\tif (!selectedItem) {\n\t\t\treturn odataModel.filteredItems;\n\t\t}\n\n\t\treturn [selectedItem, ...odataModel.filteredItems];\n\t}, [odataModel.filteredItems, selectedItem]);\n\n\tconst handleChange = (item: CollectionItem | undefined) => {\n\t\tonChange(item?.[odataModel.selectionKey]);\n\t};\n\n\treturn {\n\t\t...odataModel,\n\t\tselectedItem,\n\t\toptions,\n\t\thandleChange\n\t};\n}\n","import React from \"react\";\n\nimport { ODataSingleSelectProps, useODataCollectionModel } from \"@ryuzaki13/react-foundation-api/odata\";\nimport { CollectionItem } from \"@ryuzaki13/react-foundation-lib/odata\";\n\nimport { InputUILoading } from \"../input\";\nimport { UiBaseProps } from \"../types\";\n\nimport { useODataSelect } from \"./model/useODataSelect\";\nimport { Select } from \"./Select\";\nimport { SelectOptionContent } from \"./SelectOptionContent\";\n\ntype ODataSelectProps = Omit<ODataSingleSelectProps, \"value\"> & UiBaseProps<string | undefined> & { clearable?: boolean };\n\nfunction getODataOptionTextKey(item: CollectionItem | undefined, textKey: string, codeKey: string) {\n\tif (!item) {\n\t\treturn textKey || codeKey;\n\t}\n\n\treturn textKey || Object.keys(item).find((key) => key !== codeKey) || codeKey;\n}\n\nexport const ODataSelect: React.FC<ODataSelectProps> = ({\n\todata,\n\tsegment,\n\tmodel: initialModel,\n\tsize,\n\tlabel,\n\tdescription,\n\tdisabled,\n\tvalue,\n\tdependencies,\n\tonChange,\n\tclearable\n}) => {\n\tconst model = useODataCollectionModel(initialModel);\n\tconst odataModel = useODataSelect({\n\t\todata,\n\t\tsegment,\n\t\tmodel,\n\t\tvalue,\n\t\tdependencies,\n\t\tonChange\n\t});\n\n\tif (odataModel.isLoading) {\n\t\treturn <InputUILoading size={size} label={label} description={description} />;\n\t}\n\n\tconst hideCode = segment.hideCode ?? odata.hideCode;\n\tconst resolvedTextKey = getODataOptionTextKey(odataModel.selectedItem ?? odataModel.options[0], odataModel.textKey, odataModel.codeKey);\n\n\treturn (\n\t\t<Select\n\t\t\tsize={size}\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\toptions={odataModel.options}\n\t\t\tvalue={odataModel.selectedItem}\n\t\t\tonChange={odataModel.handleChange}\n\t\t\tgetOptionKey={(item) => item[odataModel.codeKey]}\n\t\t\tgetOptionLabel={(item) => item[resolvedTextKey]}\n\t\t\tgetOptionCode={hideCode ? undefined : (item) => item[odataModel.codeKey]}\n\t\t\tgetOptionAriaLabel={(item) =>\n\t\t\t\thideCode || item[resolvedTextKey] === item[odataModel.codeKey]\n\t\t\t\t\t? String(item[resolvedTextKey])\n\t\t\t\t\t: `${item[resolvedTextKey]} ${item[odataModel.codeKey]}`\n\t\t\t}\n\t\t\trenderValue={(item) => (\n\t\t\t\t<SelectOptionContent label={item[resolvedTextKey]} code={hideCode ? undefined : item[odataModel.codeKey]} />\n\t\t\t)}\n\t\t\trenderOption={(item) => (\n\t\t\t\t<SelectOptionContent\n\t\t\t\t\tlabel={item[resolvedTextKey]}\n\t\t\t\t\tcode={hideCode ? undefined : item[odataModel.codeKey]}\n\t\t\t\t\thighlight={odataModel.debouncedQuery}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\tsearchable\n\t\t\tquery={odataModel.query}\n\t\t\tonQuery={odataModel.setQuery}\n\t\t\tdefaultFilter={false}\n\t\t\tdisabled={disabled || odataModel.isLoading}\n\t\t\tplaceholder={odataModel.placeholder}\n\t\t\tloadingState=\"Загрузка...\"\n\t\t\terrorState={odataModel.isError ? \"Ошибка загрузки\" : undefined}\n\t\t\temptyState={!odataModel.isLoading && !odataModel.isError ? \"Нет данных\" : undefined}\n\t\t\tclearable={clearable}\n\t\t/>\n\t);\n};\n"],"mappings":";;;;;;;;AAYA,SAAgB,EAAe,EAAE,UAAO,YAAS,UAAO,UAAO,iBAAc,eAAmC;CAC/G,IAAM,IAAa,EAAmB;EACrC;EACA;EACA;EACA,OAAO,IAAQ,CAAC,CAAK,IAAI,CAAC;EAC1B;CACD,CAAC,GAEK,IAAe,EAAW,cAAc,IACxC,IAAU,QACV,IAIE,CAAC,GAAc,GAAG,EAAW,aAAa,IAHzC,EAAW,eAIjB,CAAC,EAAW,eAAe,CAAY,CAAC,GAErC,KAAgB,MAAqC;EAC1D,EAAS,IAAO,EAAW,aAAa;CACzC;CAEA,OAAO;EACN,GAAG;EACH;EACA;EACA;CACD;AACD;;;AC1BA,SAAS,EAAsB,GAAkC,GAAiB,GAAiB;CAKlG,OAJK,IAIE,KAAW,OAAO,KAAK,CAAI,CAAC,CAAC,MAAM,MAAQ,MAAQ,CAAO,KAAK,IAH9D,KAAW;AAIpB;AAEA,IAAa,KAA2C,EACvD,UACA,YACA,OAAO,GACP,SACA,UACA,gBACA,aACA,UACA,iBACA,aACA,mBACK;CAEL,IAAM,IAAa,EAAe;EACjC;EACA;EACA,OAJa,EAAwB,CAIrC;EACA;EACA;EACA;CACD,CAAC;CAED,IAAI,EAAW,WACd,OAAO,kBAAC,GAAD;EAAsB;EAAa;EAAoB;CAAc,CAAA;CAG7E,IAAM,IAAW,EAAQ,YAAY,EAAM,UACrC,IAAkB,EAAsB,EAAW,gBAAgB,EAAW,QAAQ,IAAI,EAAW,SAAS,EAAW,OAAO;CAEtI,OACC,kBAAC,GAAD;EACO;EACC;EACM;EACb,SAAS,EAAW;EACpB,OAAO,EAAW;EAClB,UAAU,EAAW;EACrB,eAAe,MAAS,EAAK,EAAW;EACxC,iBAAiB,MAAS,EAAK;EAC/B,eAAe,IAAW,KAAA,KAAa,MAAS,EAAK,EAAW;EAChE,qBAAqB,MACpB,KAAY,EAAK,OAAqB,EAAK,EAAW,WACnD,OAAO,EAAK,EAAgB,IAC5B,GAAG,EAAK,GAAiB,GAAG,EAAK,EAAW;EAEhD,cAAc,MACb,kBAAC,GAAD;GAAqB,OAAO,EAAK;GAAkB,MAAM,IAAW,KAAA,IAAY,EAAK,EAAW;EAAW,CAAA;EAE5G,eAAe,MACd,kBAAC,GAAD;GACC,OAAO,EAAK;GACZ,MAAM,IAAW,KAAA,IAAY,EAAK,EAAW;GAC7C,WAAW,EAAW;EACtB,CAAA;EAEF,YAAA;EACA,OAAO,EAAW;EAClB,SAAS,EAAW;EACpB,eAAe;EACf,UAAU,KAAY,EAAW;EACjC,aAAa,EAAW;EACxB,cAAa;EACb,YAAY,EAAW,UAAU,oBAAoB,KAAA;EACrD,YAAY,CAAC,EAAW,aAAa,CAAC,EAAW,UAAU,eAAe,KAAA;EAC/D;CACX,CAAA;AAEH"}
|