@mantine/core 9.6.1 → 9.6.3
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/cjs/components/Combobox/use-combobox/use-combobox.cjs +1 -4
- package/cjs/components/Combobox/use-combobox/use-combobox.cjs.map +1 -1
- package/cjs/components/ComboboxPopover/ComboboxPopover.cjs +1 -1
- package/cjs/components/ComboboxPopover/ComboboxPopover.cjs.map +1 -1
- package/cjs/components/Input/InputWrapper/InputWrapper.cjs +1 -1
- package/cjs/components/Input/InputWrapper/InputWrapper.cjs.map +1 -1
- package/cjs/components/Marquee/Marquee.cjs.map +1 -1
- package/cjs/components/Marquee/Marquee.module.cjs.map +1 -1
- package/cjs/components/NumberInput/NumberInput.cjs +32 -22
- package/cjs/components/NumberInput/NumberInput.cjs.map +1 -1
- package/cjs/components/NumberInput/get-caret-position-after-paste/get-caret-position-after-paste.cjs +19 -0
- package/cjs/components/NumberInput/get-caret-position-after-paste/get-caret-position-after-paste.cjs.map +1 -0
- package/cjs/components/NumberInput/normalize-pasted-value/normalize-pasted-value.cjs +35 -0
- package/cjs/components/NumberInput/normalize-pasted-value/normalize-pasted-value.cjs.map +1 -0
- package/cjs/components/PasswordInput/PasswordInput.cjs +10 -5
- package/cjs/components/PasswordInput/PasswordInput.cjs.map +1 -1
- package/cjs/components/PinInput/PinInput.cjs.map +1 -1
- package/cjs/components/Portal/Portal.cjs +10 -1
- package/cjs/components/Portal/Portal.cjs.map +1 -1
- package/cjs/components/Rating/Rating.cjs +35 -12
- package/cjs/components/Rating/Rating.cjs.map +1 -1
- package/cjs/components/Select/Select.cjs +1 -1
- package/cjs/components/Select/Select.cjs.map +1 -1
- package/cjs/components/Slider/Thumb/Thumb.cjs +7 -2
- package/cjs/components/Slider/Thumb/Thumb.cjs.map +1 -1
- package/cjs/components/Table/Table.cjs +23 -10
- package/cjs/components/Table/Table.cjs.map +1 -1
- package/cjs/components/Tooltip/Tooltip.cjs.map +1 -1
- package/cjs/core/Box/Box.cjs +1 -1
- package/cjs/core/Box/Box.cjs.map +1 -1
- package/cjs/core/Box/style-props/style-props-data.cjs +2 -2
- package/cjs/core/Box/style-props/style-props-data.cjs.map +1 -1
- package/cjs/core/styles-api/use-styles/use-styles.cjs +32 -2
- package/cjs/core/styles-api/use-styles/use-styles.cjs.map +1 -1
- package/cjs/core/utils/shallow-equal/shallow-equal.cjs +19 -0
- package/cjs/core/utils/shallow-equal/shallow-equal.cjs.map +1 -0
- package/cjs/index.cjs +1 -1
- package/esm/components/Combobox/use-combobox/use-combobox.mjs +1 -4
- package/esm/components/Combobox/use-combobox/use-combobox.mjs.map +1 -1
- package/esm/components/ComboboxPopover/ComboboxPopover.mjs +1 -1
- package/esm/components/ComboboxPopover/ComboboxPopover.mjs.map +1 -1
- package/esm/components/Input/InputWrapper/InputWrapper.mjs +1 -1
- package/esm/components/Input/InputWrapper/InputWrapper.mjs.map +1 -1
- package/esm/components/Marquee/Marquee.mjs.map +1 -1
- package/esm/components/Marquee/Marquee.module.mjs.map +1 -1
- package/esm/components/NumberInput/NumberInput.mjs +32 -22
- package/esm/components/NumberInput/NumberInput.mjs.map +1 -1
- package/esm/components/NumberInput/get-caret-position-after-paste/get-caret-position-after-paste.mjs +19 -0
- package/esm/components/NumberInput/get-caret-position-after-paste/get-caret-position-after-paste.mjs.map +1 -0
- package/esm/components/NumberInput/normalize-pasted-value/normalize-pasted-value.mjs +35 -0
- package/esm/components/NumberInput/normalize-pasted-value/normalize-pasted-value.mjs.map +1 -0
- package/esm/components/PasswordInput/PasswordInput.mjs +12 -7
- package/esm/components/PasswordInput/PasswordInput.mjs.map +1 -1
- package/esm/components/PinInput/PinInput.mjs.map +1 -1
- package/esm/components/Portal/Portal.mjs +10 -1
- package/esm/components/Portal/Portal.mjs.map +1 -1
- package/esm/components/Rating/Rating.mjs +35 -12
- package/esm/components/Rating/Rating.mjs.map +1 -1
- package/esm/components/Select/Select.mjs +1 -1
- package/esm/components/Select/Select.mjs.map +1 -1
- package/esm/components/Slider/Thumb/Thumb.mjs +7 -2
- package/esm/components/Slider/Thumb/Thumb.mjs.map +1 -1
- package/esm/components/Table/Table.mjs +23 -10
- package/esm/components/Table/Table.mjs.map +1 -1
- package/esm/components/Tooltip/Tooltip.mjs.map +1 -1
- package/esm/core/Box/Box.mjs +2 -2
- package/esm/core/Box/Box.mjs.map +1 -1
- package/esm/core/Box/style-props/style-props-data.mjs +2 -2
- package/esm/core/Box/style-props/style-props-data.mjs.map +1 -1
- package/esm/core/styles-api/use-styles/use-styles.mjs +32 -2
- package/esm/core/styles-api/use-styles/use-styles.mjs.map +1 -1
- package/esm/core/utils/shallow-equal/shallow-equal.mjs +19 -0
- package/esm/core/utils/shallow-equal/shallow-equal.mjs.map +1 -0
- package/esm/index.mjs +2 -2
- package/lib/components/Combobox/Combobox.types.d.ts +1 -1
- package/lib/components/ComboboxPopover/ComboboxPopover.d.ts +1 -1
- package/lib/components/Marquee/Marquee.d.ts +1 -1
- package/lib/components/NumberInput/get-caret-position-after-paste/get-caret-position-after-paste.d.ts +1 -0
- package/lib/components/NumberInput/normalize-pasted-value/normalize-pasted-value.d.ts +7 -0
- package/lib/components/PinInput/PinInput.d.ts +1 -1
- package/lib/components/Slider/Thumb/Thumb.d.ts +1 -1
- package/lib/components/Tooltip/Tooltip.d.ts +1 -1
- package/lib/core/Box/style-props/index.d.ts +1 -1
- package/lib/core/Box/style-props/style-props-data.d.ts +1 -1
- package/lib/core/styles-api/use-styles/use-styles.d.ts +2 -1
- package/lib/core/utils/shallow-equal/shallow-equal.d.ts +1 -0
- package/package.json +2 -2
- package/styles/Marquee.css +1 -1
- package/styles/Marquee.layer.css +1 -1
- package/styles.css +1 -1
- package/styles.layer.css +1 -1
|
@@ -3,13 +3,15 @@ const require_resolve_class_names = require("./get-class-name/resolve-class-name
|
|
|
3
3
|
const require_resolve_styles = require("./get-style/resolve-styles/resolve-styles.cjs");
|
|
4
4
|
const require_Mantine_context = require("../../MantineProvider/Mantine.context.cjs");
|
|
5
5
|
const require_MantineThemeProvider = require("../../MantineProvider/MantineThemeProvider/MantineThemeProvider.cjs");
|
|
6
|
+
const require_shallow_equal = require("../../utils/shallow-equal/shallow-equal.cjs");
|
|
6
7
|
const require_get_class_name = require("./get-class-name/get-class-name.cjs");
|
|
7
8
|
const require_resolve_style = require("./get-style/resolve-style/resolve-style.cjs");
|
|
8
9
|
const require_get_style = require("./get-style/get-style.cjs");
|
|
9
10
|
const require_merge_vars = require("./get-style/resolve-vars/merge-vars.cjs");
|
|
10
11
|
const require_use_transformed_styles = require("./use-transformed-styles.cjs");
|
|
12
|
+
let react = require("react");
|
|
11
13
|
//#region packages/@mantine/core/src/core/styles-api/use-styles/use-styles.ts
|
|
12
|
-
function useStyles({ name, classes, props, stylesCtx, className, style, rootSelector = "root", unstyled, classNames, styles, vars, varsResolver, attributes }) {
|
|
14
|
+
function useStyles({ name, classes, props, stylesCtx, className, style, rootSelector = "root", unstyled, classNames, styles, vars, varsResolver, attributes, stable }) {
|
|
13
15
|
const theme = require_MantineThemeProvider.useMantineTheme();
|
|
14
16
|
const classNamesPrefix = require_Mantine_context.useMantineClassNamesPrefix();
|
|
15
17
|
const withStaticClasses = require_Mantine_context.useMantineWithStaticClasses();
|
|
@@ -61,7 +63,7 @@ function useStyles({ name, classes, props, stylesCtx, className, style, rootSele
|
|
|
61
63
|
style,
|
|
62
64
|
theme
|
|
63
65
|
});
|
|
64
|
-
|
|
66
|
+
const getStyles = (selector, options) => ({
|
|
65
67
|
...attributes?.[selector],
|
|
66
68
|
className: require_get_class_name.getClassName({
|
|
67
69
|
theme,
|
|
@@ -95,6 +97,34 @@ function useStyles({ name, classes, props, stylesCtx, className, style, rootSele
|
|
|
95
97
|
resolvedRootStyle
|
|
96
98
|
})
|
|
97
99
|
});
|
|
100
|
+
return useStableGetStyles(getStyles, !!stable, [
|
|
101
|
+
theme,
|
|
102
|
+
classNamesPrefix,
|
|
103
|
+
withStaticClasses,
|
|
104
|
+
headless,
|
|
105
|
+
withStylesTransform ? props : null,
|
|
106
|
+
classes,
|
|
107
|
+
unstyled,
|
|
108
|
+
className,
|
|
109
|
+
rootSelector,
|
|
110
|
+
attributes,
|
|
111
|
+
stylesCtx,
|
|
112
|
+
resolvedClassNames,
|
|
113
|
+
resolvedThemeClassNames,
|
|
114
|
+
resolvedComponentStyles,
|
|
115
|
+
resolvedThemeStyles,
|
|
116
|
+
resolvedVars,
|
|
117
|
+
resolvedRootStyle
|
|
118
|
+
]);
|
|
119
|
+
}
|
|
120
|
+
function useStableGetStyles(getStyles, stable, deps) {
|
|
121
|
+
const cache = (0, react.useRef)(null);
|
|
122
|
+
if (!stable) return getStyles;
|
|
123
|
+
if (!cache.current || !require_shallow_equal.shallowEqual(cache.current.deps, deps, 3)) cache.current = {
|
|
124
|
+
deps,
|
|
125
|
+
getStyles
|
|
126
|
+
};
|
|
127
|
+
return cache.current.getStyles;
|
|
98
128
|
}
|
|
99
129
|
//#endregion
|
|
100
130
|
exports.useStyles = useStyles;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-styles.cjs","names":["useMantineTheme","useMantineClassNamesPrefix","useMantineWithStaticClasses","useMantineIsHeadless","useStylesTransform","resolveClassNames","resolveStyles","mergeVars","resolveStyle","getClassName","getStyle"],"sources":["../../../../src/core/styles-api/use-styles/use-styles.ts"],"sourcesContent":["import { CSSProperties } from 'react';\nimport type { MantineStyleProp } from '../../Box';\nimport { FactoryPayload } from '../../factory';\nimport {\n useMantineClassNamesPrefix,\n useMantineIsHeadless,\n useMantineTheme,\n useMantineWithStaticClasses,\n} from '../../MantineProvider';\nimport { PartialVarsResolver, VarsResolver } from '../create-vars-resolver/create-vars-resolver';\nimport {\n Attributes,\n ClassNames,\n ClassNamesArray,\n GetStylesApiOptions,\n Styles,\n} from '../styles-api.types';\nimport { getClassName } from './get-class-name/get-class-name';\nimport { resolveClassNames } from './get-class-name/resolve-class-names/resolve-class-names';\nimport { getStyle } from './get-style/get-style';\nimport { resolveStyle } from './get-style/resolve-style/resolve-style';\nimport { resolveStyles } from './get-style/resolve-styles/resolve-styles';\nimport { mergeVars } from './get-style/resolve-vars/merge-vars';\nimport { useStylesTransform } from './use-transformed-styles';\n\nexport interface UseStylesInput<Payload extends FactoryPayload> {\n name: string | (string | undefined)[];\n classes: Payload['stylesNames'] extends string ? Record<string, string> : never;\n props: Payload['props'];\n stylesCtx?: Payload['ctx'];\n className?: string | undefined;\n style?: MantineStyleProp;\n rootSelector?: Payload['stylesNames'];\n unstyled?: boolean;\n classNames?: ClassNames<Payload> | ClassNamesArray<Payload>;\n styles?: Styles<Payload>;\n vars?: PartialVarsResolver<Payload>;\n varsResolver?: VarsResolver<Payload>;\n attributes?: Attributes<Payload>;\n}\n\nexport type GetStylesApi<Payload extends FactoryPayload> = (\n selector: NonNullable<Payload['stylesNames']>,\n options?: GetStylesApiOptions\n) => {\n className: string;\n style: CSSProperties;\n};\n\nexport function useStyles<Payload extends FactoryPayload>({\n name,\n classes,\n props,\n stylesCtx,\n className,\n style,\n rootSelector = 'root' as NonNullable<Payload['stylesNames']>,\n unstyled,\n classNames,\n styles,\n vars,\n varsResolver,\n attributes,\n}: UseStylesInput<Payload>): GetStylesApi<Payload> {\n const theme = useMantineTheme();\n const classNamesPrefix = useMantineClassNamesPrefix();\n const withStaticClasses = useMantineWithStaticClasses();\n const headless = useMantineIsHeadless();\n const themeName = (Array.isArray(name) ? name : [name]).filter((n) => n) as string[];\n const { withStylesTransform, getTransformedStyles } = useStylesTransform({\n props,\n stylesCtx,\n themeName,\n theme,\n });\n\n const resolvedClassNames = resolveClassNames({ theme, classNames, props, stylesCtx });\n const resolvedThemeClassNames = themeName.map((n) =>\n resolveClassNames({ theme, classNames: theme.components[n]?.classNames, props, stylesCtx })\n );\n\n const resolvedComponentStyles = withStylesTransform\n ? {}\n : resolveStyles({ theme, styles, props, stylesCtx });\n\n const resolvedThemeStyles: Record<string, any> = {};\n\n if (!withStylesTransform) {\n for (const n of themeName) {\n const resolved = resolveStyles({\n theme,\n styles: theme.components[n]?.styles,\n props,\n stylesCtx,\n });\n\n for (const key of Object.keys(resolved)) {\n resolvedThemeStyles[key] = { ...resolvedThemeStyles[key], ...resolved[key] };\n }\n }\n }\n\n const resolvedVars = mergeVars([\n headless ? {} : varsResolver?.(theme, props, stylesCtx),\n ...themeName.map((n) => theme.components?.[n]?.vars?.(theme, props, stylesCtx)),\n vars?.(theme, props, stylesCtx),\n ]);\n\n const resolvedRootStyle = resolveStyle({ style, theme });\n\n
|
|
1
|
+
{"version":3,"file":"use-styles.cjs","names":["useMantineTheme","useMantineClassNamesPrefix","useMantineWithStaticClasses","useMantineIsHeadless","useStylesTransform","resolveClassNames","resolveStyles","mergeVars","resolveStyle","getClassName","getStyle","useRef","shallowEqual"],"sources":["../../../../src/core/styles-api/use-styles/use-styles.ts"],"sourcesContent":["import { CSSProperties, useRef } from 'react';\nimport type { MantineStyleProp } from '../../Box';\nimport { FactoryPayload } from '../../factory';\nimport {\n useMantineClassNamesPrefix,\n useMantineIsHeadless,\n useMantineTheme,\n useMantineWithStaticClasses,\n} from '../../MantineProvider';\nimport { shallowEqual } from '../../utils/shallow-equal/shallow-equal';\nimport { PartialVarsResolver, VarsResolver } from '../create-vars-resolver/create-vars-resolver';\nimport {\n Attributes,\n ClassNames,\n ClassNamesArray,\n GetStylesApiOptions,\n Styles,\n} from '../styles-api.types';\nimport { getClassName } from './get-class-name/get-class-name';\nimport { resolveClassNames } from './get-class-name/resolve-class-names/resolve-class-names';\nimport { getStyle } from './get-style/get-style';\nimport { resolveStyle } from './get-style/resolve-style/resolve-style';\nimport { resolveStyles } from './get-style/resolve-styles/resolve-styles';\nimport { mergeVars } from './get-style/resolve-vars/merge-vars';\nimport { useStylesTransform } from './use-transformed-styles';\n\nexport interface UseStylesInput<Payload extends FactoryPayload> {\n name: string | (string | undefined)[];\n classes: Payload['stylesNames'] extends string ? Record<string, string> : never;\n props: Payload['props'];\n stylesCtx?: Payload['ctx'];\n className?: string | undefined;\n style?: MantineStyleProp;\n rootSelector?: Payload['stylesNames'];\n unstyled?: boolean;\n classNames?: ClassNames<Payload> | ClassNamesArray<Payload>;\n styles?: Styles<Payload>;\n vars?: PartialVarsResolver<Payload>;\n varsResolver?: VarsResolver<Payload>;\n attributes?: Attributes<Payload>;\n stable?: boolean;\n}\n\nexport type GetStylesApi<Payload extends FactoryPayload> = (\n selector: NonNullable<Payload['stylesNames']>,\n options?: GetStylesApiOptions\n) => {\n className: string;\n style: CSSProperties;\n};\n\nexport function useStyles<Payload extends FactoryPayload>({\n name,\n classes,\n props,\n stylesCtx,\n className,\n style,\n rootSelector = 'root' as NonNullable<Payload['stylesNames']>,\n unstyled,\n classNames,\n styles,\n vars,\n varsResolver,\n attributes,\n stable,\n}: UseStylesInput<Payload>): GetStylesApi<Payload> {\n const theme = useMantineTheme();\n const classNamesPrefix = useMantineClassNamesPrefix();\n const withStaticClasses = useMantineWithStaticClasses();\n const headless = useMantineIsHeadless();\n const themeName = (Array.isArray(name) ? name : [name]).filter((n) => n) as string[];\n const { withStylesTransform, getTransformedStyles } = useStylesTransform({\n props,\n stylesCtx,\n themeName,\n theme,\n });\n\n const resolvedClassNames = resolveClassNames({ theme, classNames, props, stylesCtx });\n const resolvedThemeClassNames = themeName.map((n) =>\n resolveClassNames({ theme, classNames: theme.components[n]?.classNames, props, stylesCtx })\n );\n\n const resolvedComponentStyles = withStylesTransform\n ? {}\n : resolveStyles({ theme, styles, props, stylesCtx });\n\n const resolvedThemeStyles: Record<string, any> = {};\n\n if (!withStylesTransform) {\n for (const n of themeName) {\n const resolved = resolveStyles({\n theme,\n styles: theme.components[n]?.styles,\n props,\n stylesCtx,\n });\n\n for (const key of Object.keys(resolved)) {\n resolvedThemeStyles[key] = { ...resolvedThemeStyles[key], ...resolved[key] };\n }\n }\n }\n\n const resolvedVars = mergeVars([\n headless ? {} : varsResolver?.(theme, props, stylesCtx),\n ...themeName.map((n) => theme.components?.[n]?.vars?.(theme, props, stylesCtx)),\n vars?.(theme, props, stylesCtx),\n ]);\n\n const resolvedRootStyle = resolveStyle({ style, theme });\n\n const getStyles: GetStylesApi<Payload> = (selector, options) => ({\n ...attributes?.[selector],\n\n className: getClassName({\n theme,\n options,\n themeName,\n selector,\n classNamesPrefix,\n resolvedClassNames,\n resolvedThemeClassNames,\n classes,\n unstyled,\n className,\n rootSelector,\n props,\n stylesCtx,\n withStaticClasses,\n headless,\n transformedStyles: getTransformedStyles([options?.styles, styles]),\n }),\n\n style: getStyle({\n theme,\n selector,\n options,\n props,\n stylesCtx,\n rootSelector,\n withStylesTransform,\n resolvedStyles: resolvedComponentStyles,\n resolvedThemeStyles,\n resolvedVars,\n resolvedRootStyle,\n }),\n });\n\n return useStableGetStyles(getStyles, !!stable, [\n theme,\n classNamesPrefix,\n withStaticClasses,\n headless,\n withStylesTransform ? props : null,\n classes,\n unstyled,\n className,\n rootSelector,\n attributes,\n stylesCtx,\n resolvedClassNames,\n resolvedThemeClassNames,\n resolvedComponentStyles,\n resolvedThemeStyles,\n resolvedVars,\n resolvedRootStyle,\n ]);\n}\n\nfunction useStableGetStyles<Payload extends FactoryPayload>(\n getStyles: GetStylesApi<Payload>,\n stable: boolean,\n deps: unknown[]\n): GetStylesApi<Payload> {\n const cache = useRef<{ deps: unknown[]; getStyles: GetStylesApi<Payload> }>(null);\n\n if (!stable) {\n return getStyles;\n }\n\n if (!cache.current || !shallowEqual(cache.current.deps, deps, 3)) {\n cache.current = { deps, getStyles };\n }\n\n return cache.current.getStyles;\n}\n"],"mappings":";;;;;;;;;;;;;AAmDA,SAAgB,UAA0C,EACxD,MACA,SACA,OACA,WACA,WACA,OACA,eAAe,QACf,UACA,YACA,QACA,MACA,cACA,YACA,UACiD;CACjD,MAAM,QAAQA,6BAAAA,gBAAgB;CAC9B,MAAM,mBAAmBC,wBAAAA,2BAA2B;CACpD,MAAM,oBAAoBC,wBAAAA,4BAA4B;CACtD,MAAM,WAAWC,wBAAAA,qBAAqB;CACtC,MAAM,aAAa,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI,EAAA,CAAG,QAAQ,MAAM,CAAC;CACvE,MAAM,EAAE,qBAAqB,yBAAyBC,+BAAAA,mBAAmB;EACvE;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,qBAAqBC,4BAAAA,kBAAkB;EAAE;EAAO;EAAY;EAAO;CAAU,CAAC;CACpF,MAAM,0BAA0B,UAAU,KAAK,MAC7CA,4BAAAA,kBAAkB;EAAE;EAAO,YAAY,MAAM,WAAW,EAAE,EAAE;EAAY;EAAO;CAAU,CAAC,CAC5F;CAEA,MAAM,0BAA0B,sBAC5B,CAAC,IACDC,uBAAAA,cAAc;EAAE;EAAO;EAAQ;EAAO;CAAU,CAAC;CAErD,MAAM,sBAA2C,CAAC;CAElD,IAAI,CAAC,qBACH,KAAK,MAAM,KAAK,WAAW;EACzB,MAAM,WAAWA,uBAAAA,cAAc;GAC7B;GACA,QAAQ,MAAM,WAAW,EAAE,EAAE;GAC7B;GACA;EACF,CAAC;EAED,KAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,GACpC,oBAAoB,OAAO;GAAE,GAAG,oBAAoB;GAAM,GAAG,SAAS;EAAK;CAE/E;CAGF,MAAM,eAAeC,mBAAAA,UAAU;EAC7B,WAAW,CAAC,IAAI,eAAe,OAAO,OAAO,SAAS;EACtD,GAAG,UAAU,KAAK,MAAM,MAAM,aAAa,EAAE,EAAE,OAAO,OAAO,OAAO,SAAS,CAAC;EAC9E,OAAO,OAAO,OAAO,SAAS;CAChC,CAAC;CAED,MAAM,oBAAoBC,sBAAAA,aAAa;EAAE;EAAO;CAAM,CAAC;CAEvD,MAAM,aAAoC,UAAU,aAAa;EAC/D,GAAG,aAAa;EAEhB,WAAWC,uBAAAA,aAAa;GACtB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,mBAAmB,qBAAqB,CAAC,SAAS,QAAQ,MAAM,CAAC;EACnE,CAAC;EAED,OAAOC,kBAAAA,SAAS;GACd;GACA;GACA;GACA;GACA;GACA;GACA;GACA,gBAAgB;GAChB;GACA;GACA;EACF,CAAC;CACH;CAEA,OAAO,mBAAmB,WAAW,CAAC,CAAC,QAAQ;EAC7C;EACA;EACA;EACA;EACA,sBAAsB,QAAQ;EAC9B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH;AAEA,SAAS,mBACP,WACA,QACA,MACuB;CACvB,MAAM,SAAA,GAAQC,MAAAA,OAAAA,CAA8D,IAAI;CAEhF,IAAI,CAAC,QACH,OAAO;CAGT,IAAI,CAAC,MAAM,WAAW,CAACC,sBAAAA,aAAa,MAAM,QAAQ,MAAM,MAAM,CAAC,GAC7D,MAAM,UAAU;EAAE;EAAM;CAAU;CAGpC,OAAO,MAAM,QAAQ;AACvB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
//#region packages/@mantine/core/src/core/utils/shallow-equal/shallow-equal.ts
|
|
3
|
+
function shallowEqual(a, b, depth = 1) {
|
|
4
|
+
if (Object.is(a, b)) return true;
|
|
5
|
+
if (depth === 0 || typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
6
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
7
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
8
|
+
for (let i = 0; i < a.length; i += 1) if (!shallowEqual(a[i], b[i], depth - 1)) return false;
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
const aKeys = Object.keys(a);
|
|
12
|
+
if (aKeys.length !== Object.keys(b).length) return false;
|
|
13
|
+
for (const key of aKeys) if (!Object.hasOwn(b, key) || !shallowEqual(a[key], b[key], depth - 1)) return false;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
exports.shallowEqual = shallowEqual;
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=shallow-equal.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shallow-equal.cjs","names":[],"sources":["../../../../src/core/utils/shallow-equal/shallow-equal.ts"],"sourcesContent":["export function shallowEqual(a: unknown, b: unknown, depth = 1): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n\n if (depth === 0 || typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {\n return false;\n }\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i += 1) {\n if (!shallowEqual(a[i], b[i], depth - 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n const aKeys = Object.keys(a);\n\n if (aKeys.length !== Object.keys(b).length) {\n return false;\n }\n\n for (const key of aKeys) {\n if (!Object.hasOwn(b, key) || !shallowEqual((a as any)[key], (b as any)[key], depth - 1)) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":";;AAAA,SAAgB,aAAa,GAAY,GAAY,QAAQ,GAAY;CACvE,IAAI,OAAO,GAAG,GAAG,CAAC,GAChB,OAAO;CAGT,IAAI,UAAU,KAAK,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,MAAM,QAAQ,MAAM,MACvF,OAAO;CAGT,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;EACxC,IAAI,CAAC,MAAM,QAAQ,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,QAC3D,OAAO;EAGT,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,GACjC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC,GACrC,OAAO;EAIX,OAAO;CACT;CAEA,MAAM,QAAQ,OAAO,KAAK,CAAC;CAE3B,IAAI,MAAM,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC,QAClC,OAAO;CAGT,KAAK,MAAM,OAAO,OAChB,IAAI,CAAC,OAAO,OAAO,GAAG,GAAG,KAAK,CAAC,aAAc,EAAU,MAAO,EAAU,MAAM,QAAQ,CAAC,GACrF,OAAO;CAIX,OAAO;AACT"}
|
package/cjs/index.cjs
CHANGED
|
@@ -630,7 +630,7 @@ Object.defineProperty(exports, "RemoveScroll", {
|
|
|
630
630
|
});
|
|
631
631
|
exports.RingProgress = require_RingProgress.RingProgress;
|
|
632
632
|
exports.RollingNumber = require_RollingNumber.RollingNumber;
|
|
633
|
-
exports.
|
|
633
|
+
exports.STYLE_PROPS_DATA = require_style_props_data.STYLE_PROPS_DATA;
|
|
634
634
|
exports.ScrollArea = require_ScrollArea.ScrollArea;
|
|
635
635
|
exports.ScrollAreaAutosize = require_ScrollArea.ScrollAreaAutosize;
|
|
636
636
|
exports.Scroller = require_Scroller.Scroller;
|
|
@@ -48,9 +48,7 @@ function useCombobox({ defaultOpened, opened, onOpenedChange, onDropdownClose, o
|
|
|
48
48
|
]);
|
|
49
49
|
const clearSelectedItem = useCallback(() => {
|
|
50
50
|
const root = getRootElement(targetRef.current);
|
|
51
|
-
|
|
52
|
-
selected?.removeAttribute("data-combobox-selected");
|
|
53
|
-
selected?.removeAttribute("aria-selected");
|
|
51
|
+
findElementBySelector(`#${listId.current} [data-combobox-selected]`, root)?.removeAttribute("data-combobox-selected");
|
|
54
52
|
}, []);
|
|
55
53
|
const selectOption = useCallback((index) => {
|
|
56
54
|
const root = getRootElement(targetRef.current);
|
|
@@ -62,7 +60,6 @@ function useCombobox({ defaultOpened, opened, onOpenedChange, onDropdownClose, o
|
|
|
62
60
|
if (items?.[nextIndex] && !items[nextIndex].hasAttribute("data-combobox-disabled")) {
|
|
63
61
|
clearSelectedItem();
|
|
64
62
|
items[nextIndex].setAttribute("data-combobox-selected", "true");
|
|
65
|
-
items[nextIndex].setAttribute("aria-selected", "true");
|
|
66
63
|
items[nextIndex].scrollIntoView({
|
|
67
64
|
block: "nearest",
|
|
68
65
|
behavior: scrollBehavior
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-combobox.mjs","names":[],"sources":["../../../../src/components/Combobox/use-combobox/use-combobox.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useUncontrolled } from '@mantine/hooks';\nimport { findElementBySelector, findElementsBySelector, getRootElement } from '../../../core/utils';\nimport { getFirstIndex, getNextIndex, getPreviousIndex } from './get-index/get-index';\n\nexport type ComboboxDropdownEventSource = 'keyboard' | 'mouse' | 'unknown';\n\nexport interface ComboboxStore {\n /** Current dropdown opened state */\n dropdownOpened: boolean;\n\n /** Opens dropdown */\n openDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Closes dropdown */\n closeDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Toggles dropdown opened state */\n toggleDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Selected option index ref */\n selectedOptionIndex: number;\n\n /** Returns currently selected option index or `-1` if none of the options is selected */\n getSelectedOptionIndex: () => number;\n\n /** Selects `Combobox.Option` by index */\n selectOption: (index: number) => void;\n\n /** Selects first `Combobox.Option` with `active` prop.\n * If there are no such options, the function does nothing.\n */\n selectActiveOption: () => string | null;\n\n /** Selects first `Combobox.Option` that is not disabled.\n * If there are no such options, the function does nothing.\n * */\n selectFirstOption: () => string | null;\n\n /** Selects next `Combobox.Option` that is not disabled.\n * If the current option is the last one, the function selects first option, if `loop` is true.\n */\n selectNextOption: () => string | null;\n\n /** Selects previous `Combobox.Option` that is not disabled.\n * If the current option is the first one, the function selects last option, if `loop` is true.\n * */\n selectPreviousOption: () => string | null;\n\n /** Resets selected option index to -1, removes `data-combobox-selected` from selected option */\n resetSelectedOption: () => void;\n\n /** Triggers `onClick` event of selected option.\n * If there is no selected option, the function does nothing.\n */\n clickSelectedOption: () => void;\n\n /** Updates selected option index to currently selected or active option.\n * The function is required to be used with searchable components to update selected option index\n * when options list changes based on search query.\n */\n updateSelectedOptionIndex: (\n target?: 'active' | 'selected' | number,\n options?: { scrollIntoView?: boolean }\n ) => void;\n\n /** List id, used for `aria-*` attributes */\n listId: string | null;\n\n /** Sets list id */\n setListId: (id: string) => void;\n\n /** Ref of `Combobox.Search` input */\n searchRef: React.RefObject<HTMLInputElement | null>;\n\n /** Moves focus to `Combobox.Search` input */\n focusSearchInput: () => void;\n\n /** Ref of the target element */\n targetRef: React.RefObject<HTMLElement | null>;\n\n /** Moves focus to the target element */\n focusTarget: () => void;\n}\n\nexport interface UseComboboxOptions {\n /** Default value for `dropdownOpened`, `false` by default. Used when the component is uncontrolled */\n defaultOpened?: boolean;\n\n /** Controlled `dropdownOpened` state. When set, the dropdown opened state is controlled by the parent component */\n opened?: boolean;\n\n /** Called when `dropdownOpened` state changes. Required for controlled mode */\n onOpenedChange?: (opened: boolean) => void;\n\n /** Called when dropdown closes with event source: keyboard, mouse or unknown. Useful for analytics or side effects on dropdown closure */\n onDropdownClose?: (eventSource: ComboboxDropdownEventSource) => void;\n\n /** Called when dropdown opens with event source: keyboard, mouse or unknown. Useful for analytics or side effects on dropdown opening */\n onDropdownOpen?: (eventSource: ComboboxDropdownEventSource) => void;\n\n /** Determines whether arrow key presses should loop through items (first to last and last to first). Defaults to `true` */\n loop?: boolean;\n\n /** `behavior` passed down to `element.scrollIntoView`. Controls the scrolling animation when options are scrolled into view. Defaults to `'instant'` */\n scrollBehavior?: ScrollBehavior;\n}\n\nexport function useCombobox({\n defaultOpened,\n opened,\n onOpenedChange,\n onDropdownClose,\n onDropdownOpen,\n loop = true,\n scrollBehavior = 'instant',\n}: UseComboboxOptions = {}): ComboboxStore {\n const [dropdownOpened, setDropdownOpened] = useUncontrolled({\n value: opened,\n defaultValue: defaultOpened,\n finalValue: false,\n onChange: onOpenedChange,\n });\n\n const listId = useRef<string | null>(null);\n const selectedOptionIndex = useRef<number>(-1);\n const searchRef = useRef<HTMLInputElement | null>(null);\n const targetRef = useRef<HTMLElement | null>(null);\n const focusSearchTimeout = useRef<number>(-1);\n const focusTargetTimeout = useRef<number>(-1);\n const selectedIndexUpdateTimeout = useRef<number>(-1);\n\n const openDropdown: ComboboxStore['openDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (!dropdownOpened) {\n setDropdownOpened(true);\n onDropdownOpen?.(eventSource);\n }\n },\n [setDropdownOpened, onDropdownOpen, dropdownOpened]\n );\n\n const closeDropdown: ComboboxStore['closeDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (dropdownOpened) {\n setDropdownOpened(false);\n onDropdownClose?.(eventSource);\n }\n },\n [setDropdownOpened, onDropdownClose, dropdownOpened]\n );\n\n const toggleDropdown: ComboboxStore['toggleDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (dropdownOpened) {\n closeDropdown(eventSource);\n } else {\n openDropdown(eventSource);\n }\n },\n [closeDropdown, openDropdown, dropdownOpened]\n );\n\n const clearSelectedItem = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const selected = findElementBySelector(`#${listId.current} [data-combobox-selected]`, root);\n selected?.removeAttribute('data-combobox-selected');\n selected?.removeAttribute('aria-selected');\n }, []);\n\n const selectOption = useCallback(\n (index: number) => {\n const root = getRootElement(targetRef.current);\n const list = findElementBySelector(`#${listId.current!}`, root);\n const items = list\n ? findElementsBySelector<HTMLDivElement>('[data-combobox-option]', list)\n : null;\n\n if (!items) {\n return null;\n }\n\n const nextIndex = index >= items!.length ? 0 : index < 0 ? items!.length - 1 : index;\n selectedOptionIndex.current = nextIndex;\n\n if (items?.[nextIndex] && !items[nextIndex].hasAttribute('data-combobox-disabled')) {\n clearSelectedItem();\n items[nextIndex].setAttribute('data-combobox-selected', 'true');\n items[nextIndex].setAttribute('aria-selected', 'true');\n items[nextIndex].scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n return items[nextIndex].id;\n }\n\n return null;\n },\n [scrollBehavior, clearSelectedItem]\n );\n\n const selectActiveOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const activeOption = findElementBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-active]`,\n root\n );\n\n if (activeOption) {\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const index = items.findIndex((option) => option === activeOption);\n return selectOption(index);\n }\n\n return selectOption(0);\n }, [selectOption]);\n\n const selectNextOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getNextIndex(selectedOptionIndex.current, items, loop));\n }, [selectOption, loop]);\n\n const selectPreviousOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getPreviousIndex(selectedOptionIndex.current, items, loop));\n }, [selectOption, loop]);\n\n const selectFirstOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getFirstIndex(items));\n }, [selectOption]);\n\n const updateSelectedOptionIndex: ComboboxStore['updateSelectedOptionIndex'] = useCallback(\n (target = 'selected', options) => {\n if (typeof target === 'number') {\n selectedOptionIndex.current = target;\n const root = getRootElement(targetRef.current);\n\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n\n if (options?.scrollIntoView) {\n items[target]?.scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n }\n return;\n }\n\n selectedIndexUpdateTimeout.current = window.setTimeout(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const index = items.findIndex((option) => option.hasAttribute(`data-combobox-${target}`));\n\n selectedOptionIndex.current = index;\n\n if (options?.scrollIntoView) {\n items[index]?.scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n }\n }, 0);\n },\n []\n );\n\n const resetSelectedOption = useCallback(() => {\n selectedOptionIndex.current = -1;\n clearSelectedItem();\n }, [clearSelectedItem]);\n\n const clickSelectedOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const item = items?.[selectedOptionIndex.current];\n item?.click();\n }, []);\n\n const setListId = useCallback((id: string) => {\n listId.current = id;\n }, []);\n\n const focusSearchInput = useCallback(() => {\n focusSearchTimeout.current = window.setTimeout(() => searchRef.current?.focus(), 0);\n }, []);\n\n const focusTarget = useCallback(() => {\n focusTargetTimeout.current = window.setTimeout(() => targetRef.current?.focus(), 0);\n }, []);\n\n const getSelectedOptionIndex = useCallback(() => selectedOptionIndex.current, []);\n\n useEffect(\n () => () => {\n window.clearTimeout(focusSearchTimeout.current);\n window.clearTimeout(focusTargetTimeout.current);\n window.clearTimeout(selectedIndexUpdateTimeout.current);\n },\n []\n );\n\n return {\n dropdownOpened,\n openDropdown,\n closeDropdown,\n toggleDropdown,\n\n selectedOptionIndex: selectedOptionIndex.current,\n getSelectedOptionIndex,\n selectOption,\n selectFirstOption,\n selectActiveOption,\n selectNextOption,\n selectPreviousOption,\n resetSelectedOption,\n updateSelectedOptionIndex,\n\n listId: listId.current,\n setListId,\n clickSelectedOption,\n\n searchRef,\n focusSearchInput,\n\n targetRef,\n focusTarget,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-combobox.mjs","names":[],"sources":["../../../../src/components/Combobox/use-combobox/use-combobox.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useUncontrolled } from '@mantine/hooks';\nimport { findElementBySelector, findElementsBySelector, getRootElement } from '../../../core/utils';\nimport { getFirstIndex, getNextIndex, getPreviousIndex } from './get-index/get-index';\n\nexport type ComboboxDropdownEventSource = 'keyboard' | 'mouse' | 'unknown';\n\nexport interface ComboboxStore {\n /** Current dropdown opened state */\n dropdownOpened: boolean;\n\n /** Opens dropdown */\n openDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Closes dropdown */\n closeDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Toggles dropdown opened state */\n toggleDropdown: (eventSource?: ComboboxDropdownEventSource) => void;\n\n /** Selected option index ref */\n selectedOptionIndex: number;\n\n /** Returns currently selected option index or `-1` if none of the options is selected */\n getSelectedOptionIndex: () => number;\n\n /** Selects `Combobox.Option` by index */\n selectOption: (index: number) => void;\n\n /** Selects first `Combobox.Option` with `active` prop.\n * If there are no such options, the function does nothing.\n */\n selectActiveOption: () => string | null;\n\n /** Selects first `Combobox.Option` that is not disabled.\n * If there are no such options, the function does nothing.\n * */\n selectFirstOption: () => string | null;\n\n /** Selects next `Combobox.Option` that is not disabled.\n * If the current option is the last one, the function selects first option, if `loop` is true.\n */\n selectNextOption: () => string | null;\n\n /** Selects previous `Combobox.Option` that is not disabled.\n * If the current option is the first one, the function selects last option, if `loop` is true.\n * */\n selectPreviousOption: () => string | null;\n\n /** Resets selected option index to -1, removes `data-combobox-selected` from selected option */\n resetSelectedOption: () => void;\n\n /** Triggers `onClick` event of selected option.\n * If there is no selected option, the function does nothing.\n */\n clickSelectedOption: () => void;\n\n /** Updates selected option index to currently selected or active option.\n * The function is required to be used with searchable components to update selected option index\n * when options list changes based on search query.\n */\n updateSelectedOptionIndex: (\n target?: 'active' | 'selected' | number,\n options?: { scrollIntoView?: boolean }\n ) => void;\n\n /** List id, used for `aria-*` attributes */\n listId: string | null;\n\n /** Sets list id */\n setListId: (id: string) => void;\n\n /** Ref of `Combobox.Search` input */\n searchRef: React.RefObject<HTMLInputElement | null>;\n\n /** Moves focus to `Combobox.Search` input */\n focusSearchInput: () => void;\n\n /** Ref of the target element */\n targetRef: React.RefObject<HTMLElement | null>;\n\n /** Moves focus to the target element */\n focusTarget: () => void;\n}\n\nexport interface UseComboboxOptions {\n /** Default value for `dropdownOpened`, `false` by default. Used when the component is uncontrolled */\n defaultOpened?: boolean;\n\n /** Controlled `dropdownOpened` state. When set, the dropdown opened state is controlled by the parent component */\n opened?: boolean;\n\n /** Called when `dropdownOpened` state changes. Required for controlled mode */\n onOpenedChange?: (opened: boolean) => void;\n\n /** Called when dropdown closes with event source: keyboard, mouse or unknown. Useful for analytics or side effects on dropdown closure */\n onDropdownClose?: (eventSource: ComboboxDropdownEventSource) => void;\n\n /** Called when dropdown opens with event source: keyboard, mouse or unknown. Useful for analytics or side effects on dropdown opening */\n onDropdownOpen?: (eventSource: ComboboxDropdownEventSource) => void;\n\n /** Determines whether arrow key presses should loop through items (first to last and last to first). Defaults to `true` */\n loop?: boolean;\n\n /** `behavior` passed down to `element.scrollIntoView`. Controls the scrolling animation when options are scrolled into view. Defaults to `'instant'` */\n scrollBehavior?: ScrollBehavior;\n}\n\nexport function useCombobox({\n defaultOpened,\n opened,\n onOpenedChange,\n onDropdownClose,\n onDropdownOpen,\n loop = true,\n scrollBehavior = 'instant',\n}: UseComboboxOptions = {}): ComboboxStore {\n const [dropdownOpened, setDropdownOpened] = useUncontrolled({\n value: opened,\n defaultValue: defaultOpened,\n finalValue: false,\n onChange: onOpenedChange,\n });\n\n const listId = useRef<string | null>(null);\n const selectedOptionIndex = useRef<number>(-1);\n const searchRef = useRef<HTMLInputElement | null>(null);\n const targetRef = useRef<HTMLElement | null>(null);\n const focusSearchTimeout = useRef<number>(-1);\n const focusTargetTimeout = useRef<number>(-1);\n const selectedIndexUpdateTimeout = useRef<number>(-1);\n\n const openDropdown: ComboboxStore['openDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (!dropdownOpened) {\n setDropdownOpened(true);\n onDropdownOpen?.(eventSource);\n }\n },\n [setDropdownOpened, onDropdownOpen, dropdownOpened]\n );\n\n const closeDropdown: ComboboxStore['closeDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (dropdownOpened) {\n setDropdownOpened(false);\n onDropdownClose?.(eventSource);\n }\n },\n [setDropdownOpened, onDropdownClose, dropdownOpened]\n );\n\n const toggleDropdown: ComboboxStore['toggleDropdown'] = useCallback(\n (eventSource = 'unknown') => {\n if (dropdownOpened) {\n closeDropdown(eventSource);\n } else {\n openDropdown(eventSource);\n }\n },\n [closeDropdown, openDropdown, dropdownOpened]\n );\n\n const clearSelectedItem = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const selected = findElementBySelector(`#${listId.current} [data-combobox-selected]`, root);\n selected?.removeAttribute('data-combobox-selected');\n }, []);\n\n const selectOption = useCallback(\n (index: number) => {\n const root = getRootElement(targetRef.current);\n const list = findElementBySelector(`#${listId.current!}`, root);\n const items = list\n ? findElementsBySelector<HTMLDivElement>('[data-combobox-option]', list)\n : null;\n\n if (!items) {\n return null;\n }\n\n const nextIndex = index >= items!.length ? 0 : index < 0 ? items!.length - 1 : index;\n selectedOptionIndex.current = nextIndex;\n\n if (items?.[nextIndex] && !items[nextIndex].hasAttribute('data-combobox-disabled')) {\n clearSelectedItem();\n items[nextIndex].setAttribute('data-combobox-selected', 'true');\n items[nextIndex].scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n return items[nextIndex].id;\n }\n\n return null;\n },\n [scrollBehavior, clearSelectedItem]\n );\n\n const selectActiveOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const activeOption = findElementBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-active]`,\n root\n );\n\n if (activeOption) {\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const index = items.findIndex((option) => option === activeOption);\n return selectOption(index);\n }\n\n return selectOption(0);\n }, [selectOption]);\n\n const selectNextOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getNextIndex(selectedOptionIndex.current, items, loop));\n }, [selectOption, loop]);\n\n const selectPreviousOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getPreviousIndex(selectedOptionIndex.current, items, loop));\n }, [selectOption, loop]);\n\n const selectFirstOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n return selectOption(getFirstIndex(items));\n }, [selectOption]);\n\n const updateSelectedOptionIndex: ComboboxStore['updateSelectedOptionIndex'] = useCallback(\n (target = 'selected', options) => {\n if (typeof target === 'number') {\n selectedOptionIndex.current = target;\n const root = getRootElement(targetRef.current);\n\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n\n if (options?.scrollIntoView) {\n items[target]?.scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n }\n return;\n }\n\n selectedIndexUpdateTimeout.current = window.setTimeout(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const index = items.findIndex((option) => option.hasAttribute(`data-combobox-${target}`));\n\n selectedOptionIndex.current = index;\n\n if (options?.scrollIntoView) {\n items[index]?.scrollIntoView({ block: 'nearest', behavior: scrollBehavior });\n }\n }, 0);\n },\n []\n );\n\n const resetSelectedOption = useCallback(() => {\n selectedOptionIndex.current = -1;\n clearSelectedItem();\n }, [clearSelectedItem]);\n\n const clickSelectedOption = useCallback(() => {\n const root = getRootElement(targetRef.current);\n const items = findElementsBySelector<HTMLDivElement>(\n `#${listId.current} [data-combobox-option]`,\n root\n );\n const item = items?.[selectedOptionIndex.current];\n item?.click();\n }, []);\n\n const setListId = useCallback((id: string) => {\n listId.current = id;\n }, []);\n\n const focusSearchInput = useCallback(() => {\n focusSearchTimeout.current = window.setTimeout(() => searchRef.current?.focus(), 0);\n }, []);\n\n const focusTarget = useCallback(() => {\n focusTargetTimeout.current = window.setTimeout(() => targetRef.current?.focus(), 0);\n }, []);\n\n const getSelectedOptionIndex = useCallback(() => selectedOptionIndex.current, []);\n\n useEffect(\n () => () => {\n window.clearTimeout(focusSearchTimeout.current);\n window.clearTimeout(focusTargetTimeout.current);\n window.clearTimeout(selectedIndexUpdateTimeout.current);\n },\n []\n );\n\n return {\n dropdownOpened,\n openDropdown,\n closeDropdown,\n toggleDropdown,\n\n selectedOptionIndex: selectedOptionIndex.current,\n getSelectedOptionIndex,\n selectOption,\n selectFirstOption,\n selectActiveOption,\n selectNextOption,\n selectPreviousOption,\n resetSelectedOption,\n updateSelectedOptionIndex,\n\n listId: listId.current,\n setListId,\n clickSelectedOption,\n\n searchRef,\n focusSearchInput,\n\n targetRef,\n focusTarget,\n };\n}\n"],"mappings":"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"}
|
|
@@ -125,7 +125,6 @@ const ComboboxPopover = genericFactory((_props) => {
|
|
|
125
125
|
onDropdownClose: () => {
|
|
126
126
|
onDropdownClose?.();
|
|
127
127
|
combobox.resetSelectedOption();
|
|
128
|
-
if (searchable) combobox.focusTarget();
|
|
129
128
|
}
|
|
130
129
|
});
|
|
131
130
|
const handleSearchChange = (val) => {
|
|
@@ -160,6 +159,7 @@ const ComboboxPopover = genericFactory((_props) => {
|
|
|
160
159
|
unstyled,
|
|
161
160
|
attributes,
|
|
162
161
|
onOptionSubmit: handleOptionSubmit,
|
|
162
|
+
returnFocus: true,
|
|
163
163
|
...comboboxProps,
|
|
164
164
|
...others,
|
|
165
165
|
children: [children, searchable ? /* @__PURE__ */ jsx(SearchableDropdown, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboboxPopover.mjs","names":["comboboxClasses"],"sources":["../../../src/components/ComboboxPopover/ComboboxPopover.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport cx from 'clsx';\nimport { useUncontrolled } from '@mantine/hooks';\nimport {\n Factory,\n genericFactory,\n Primitive,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n} from '../../core';\nimport { CheckIcon } from '../Checkbox';\nimport {\n Combobox,\n ComboboxData,\n ComboboxItem,\n ComboboxLikeRenderOptionInput,\n ComboboxLikeStylesNames,\n ComboboxProps,\n defaultOptionsFilter,\n getOptionsLockup,\n getParsedComboboxData,\n isOptionsGroup,\n OptionsDropdown,\n OptionsFilter,\n useCombobox,\n} from '../Combobox';\nimport { ComboboxParsedItem } from '../Combobox/Combobox.types';\nimport { isEmptyComboboxData } from '../Combobox/OptionsDropdown/is-empty-combobox-data';\nimport { ScrollArea, ScrollAreaProps } from '../ScrollArea';\nimport { ComboboxPopoverValue } from './ComboboxPopover.types';\nimport { ComboboxPopoverTarget } from './ComboboxPopoverTarget';\nimport comboboxClasses from '../Combobox/Combobox.module.css';\n\nfunction isValueChecked(value: Primitive | Primitive[] | undefined | null, optionValue: Primitive) {\n return Array.isArray(value) ? value.includes(optionValue) : value === optionValue;\n}\n\ninterface OptionProps {\n data: ComboboxParsedItem<Primitive>;\n withCheckIcon?: boolean;\n withAlignedLabels?: boolean;\n value?: Primitive | Primitive[] | null;\n checkIconPosition?: 'left' | 'right';\n unstyled: boolean | undefined;\n renderOption?: (input: ComboboxLikeRenderOptionInput<any>) => React.ReactNode;\n}\n\nfunction Option({\n data,\n withCheckIcon,\n withAlignedLabels,\n value,\n checkIconPosition,\n unstyled,\n renderOption,\n}: OptionProps) {\n if (isOptionsGroup(data)) {\n const options = data.items.map((item) => (\n <Option\n data={item}\n value={value}\n key={`${item.value}`}\n unstyled={unstyled}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n checkIconPosition={checkIconPosition}\n renderOption={renderOption}\n />\n ));\n return <Combobox.Group label={data.group}>{options}</Combobox.Group>;\n }\n\n const checked = isValueChecked(value, data.value);\n const check =\n withCheckIcon &&\n (checked ? (\n <CheckIcon className={comboboxClasses.optionsDropdownCheckIcon} />\n ) : withAlignedLabels ? (\n <div className={comboboxClasses.optionsDropdownCheckPlaceholder} />\n ) : null);\n\n const defaultContent = (\n <>\n {checkIconPosition === 'left' && check}\n <span>{data.label}</span>\n {checkIconPosition === 'right' && check}\n </>\n );\n\n return (\n <Combobox.Option\n value={data.value}\n disabled={data.disabled}\n className={cx({ [comboboxClasses.optionsDropdownOption]: !unstyled })}\n data-reverse={checkIconPosition === 'right' || undefined}\n data-checked={checked || undefined}\n aria-selected={checked}\n active={checked}\n >\n {typeof renderOption === 'function'\n ? renderOption({ option: data, checked })\n : defaultContent}\n </Combobox.Option>\n );\n}\n\ninterface SearchableDropdownProps {\n data: ComboboxParsedItem<Primitive>[];\n filter: OptionsFilter<Primitive> | undefined;\n search: string;\n limit: number | undefined;\n nothingFoundMessage: React.ReactNode | undefined;\n withScrollArea: boolean | undefined;\n maxDropdownHeight: number | string | undefined;\n value: Primitive | Primitive[] | null;\n checkIconPosition: 'left' | 'right' | undefined;\n withCheckIcon: boolean | undefined;\n withAlignedLabels: boolean | undefined;\n unstyled: boolean | undefined;\n renderOption?: (input: ComboboxLikeRenderOptionInput<any>) => React.ReactNode;\n scrollAreaProps: ScrollAreaProps | undefined;\n onSearchChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\nfunction SearchableDropdown({\n data,\n filter,\n search,\n limit,\n nothingFoundMessage,\n withScrollArea = true,\n maxDropdownHeight,\n value,\n checkIconPosition,\n withCheckIcon = false,\n withAlignedLabels = false,\n unstyled,\n renderOption,\n scrollAreaProps,\n onSearchChange,\n}: SearchableDropdownProps) {\n const filteredData = (filter || defaultOptionsFilter)({\n options: data,\n search,\n limit: limit ?? Infinity,\n });\n const isEmpty = isEmptyComboboxData(filteredData);\n\n const options = filteredData.map((item, index) => (\n <Option\n data={item}\n key={\n isOptionsGroup(item)\n ? `group-${typeof item.group === 'string' ? item.group : index}`\n : `${item.value}`\n }\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n value={value}\n checkIconPosition={checkIconPosition}\n unstyled={unstyled}\n renderOption={renderOption}\n />\n ));\n\n return (\n <Combobox.Dropdown data-composed>\n <Combobox.Search value={search} onChange={onSearchChange} placeholder=\"Search...\" />\n <Combobox.Options>\n {withScrollArea ? (\n <ScrollArea.Autosize\n mah={maxDropdownHeight ?? 220}\n type=\"scroll\"\n scrollbarSize=\"var(--combobox-padding)\"\n offsetScrollbars=\"y\"\n {...scrollAreaProps}\n >\n {options}\n </ScrollArea.Autosize>\n ) : (\n options\n )}\n {isEmpty && nothingFoundMessage && <Combobox.Empty>{nothingFoundMessage}</Combobox.Empty>}\n </Combobox.Options>\n </Combobox.Dropdown>\n );\n}\n\nexport type ComboboxPopoverStylesNames = ComboboxLikeStylesNames | 'search';\n\nexport interface ComboboxPopoverProps<\n Multiple extends boolean = false,\n Value extends Primitive = string,\n> extends StylesApiProps<ComboboxPopoverFactory> {\n /** If set, multiple items can be selected at the same time */\n multiple?: Multiple;\n\n /** Controlled component value */\n value?: ComboboxPopoverValue<Multiple, Value>;\n\n /** Uncontrolled component default value */\n defaultValue?: ComboboxPopoverValue<Multiple, Value>;\n\n /** Called when value changes */\n onChange?: (value: ComboboxPopoverValue<Multiple, Value>) => void;\n\n /** Data used to generate options */\n data?: ComboboxData<Value>;\n\n /** Controlled dropdown opened state */\n dropdownOpened?: boolean;\n\n /** Uncontrolled dropdown initial opened state */\n defaultDropdownOpened?: boolean;\n\n /** Called when dropdown opens */\n onDropdownOpen?: () => void;\n\n /** Called when dropdown closes */\n onDropdownClose?: () => void;\n\n /** Called when option is submitted from dropdown with mouse click or Enter key */\n onOptionSubmit?: (value: Value) => void;\n\n /** Props passed down to Combobox component */\n comboboxProps?: ComboboxProps;\n\n /** Function based on which items are filtered and sorted */\n filter?: OptionsFilter<Value>;\n\n /** Maximum number of options displayed at a time @default Infinity */\n limit?: number;\n\n /** Determines whether the options should be wrapped with ScrollArea.AutoSize @default true */\n withScrollArea?: boolean;\n\n /** max-height of the dropdown @default 250 */\n maxDropdownHeight?: number | string;\n\n /** If set, the first option is selected when dropdown opens @default false */\n selectFirstOptionOnDropdownOpen?: boolean;\n\n /** Displays check icon near the selected option label @default true */\n withCheckIcon?: boolean;\n\n /** Aligns unchecked labels with the checked one @default false */\n withAlignedLabels?: boolean;\n\n /** Position of the check icon relative to the option label @default 'left' */\n checkIconPosition?: 'left' | 'right';\n\n /** Message displayed when no options match the search query or when there is no data */\n nothingFoundMessage?: React.ReactNode;\n\n /** Allows searching through options @default false */\n searchable?: boolean;\n\n /** Controlled search value */\n searchValue?: string;\n\n /** Default search value */\n defaultSearchValue?: string;\n\n /** Called when search changes */\n onSearchChange?: (value: string) => void;\n\n /** Allows deselecting the selected option by clicking it (only for single mode) @default true */\n allowDeselect?: boolean;\n\n /** A function to render content of the option, replaces the default content of the option */\n renderOption?: (item: ComboboxLikeRenderOptionInput<ComboboxItem>) => React.ReactNode;\n\n /** Props passed down to the underlying ScrollArea component in the dropdown */\n scrollAreaProps?: ScrollAreaProps;\n\n /** Props passed down to the hidden input */\n hiddenInputProps?: Omit<React.ComponentProps<'input'>, 'value'>;\n\n /** Hidden input name for form submission */\n name?: string;\n\n /** Hidden input form for form submission */\n form?: string;\n\n /** Content of the component */\n children?: React.ReactNode;\n\n /** Divider used to separate values in the hidden input value attribute @default ',' */\n hiddenInputValuesDivider?: string;\n}\n\nexport type ComboboxPopoverFactory = Factory<{\n props: ComboboxPopoverProps;\n ref: HTMLDivElement;\n stylesNames: ComboboxPopoverStylesNames;\n signature: <Multiple extends boolean = false, Value extends Primitive = string>(\n props: ComboboxPopoverProps<Multiple, Value>\n ) => React.JSX.Element;\n staticComponents: {\n Target: typeof ComboboxPopoverTarget;\n };\n}>;\n\nconst defaultProps = {\n withCheckIcon: true,\n allowDeselect: true,\n checkIconPosition: 'left',\n hiddenInputValuesDivider: ',',\n} satisfies Partial<ComboboxPopoverProps>;\n\nexport const ComboboxPopover = genericFactory<ComboboxPopoverFactory>((_props) => {\n const props = useProps('ComboboxPopover', defaultProps as any, _props);\n const {\n classNames,\n styles,\n unstyled,\n vars,\n children,\n multiple,\n value,\n defaultValue,\n onChange,\n data,\n dropdownOpened,\n defaultDropdownOpened,\n onDropdownOpen,\n onDropdownClose,\n onOptionSubmit,\n comboboxProps,\n filter,\n limit,\n withScrollArea,\n maxDropdownHeight,\n selectFirstOptionOnDropdownOpen,\n withCheckIcon,\n withAlignedLabels,\n checkIconPosition,\n nothingFoundMessage,\n searchable,\n searchValue,\n defaultSearchValue,\n onSearchChange,\n allowDeselect,\n renderOption,\n scrollAreaProps,\n hiddenInputProps,\n name,\n form,\n hiddenInputValuesDivider,\n attributes,\n ...others\n } = props;\n\n const parsedData = useMemo(() => getParsedComboboxData(data), [data]);\n const optionsLockup = useMemo(() => getOptionsLockup(parsedData), [parsedData]);\n\n const [_value, setValue] = useUncontrolled({\n value,\n defaultValue,\n finalValue: multiple ? ([] as any) : null,\n onChange,\n });\n\n const [_searchValue, setSearchValue] = useUncontrolled({\n value: searchValue,\n defaultValue: defaultSearchValue,\n finalValue: '',\n onChange: onSearchChange,\n });\n\n const combobox = useCombobox({\n opened: dropdownOpened,\n defaultOpened: defaultDropdownOpened,\n onDropdownOpen: () => {\n onDropdownOpen?.();\n if (searchable) {\n combobox.focusSearchInput();\n }\n if (selectFirstOptionOnDropdownOpen) {\n combobox.selectFirstOption();\n }\n },\n onDropdownClose: () => {\n onDropdownClose?.();\n combobox.resetSelectedOption();\n if (searchable) {\n combobox.focusTarget();\n }\n },\n });\n\n const handleSearchChange = (val: string) => {\n setSearchValue(val);\n combobox.resetSelectedOption();\n };\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<ComboboxPopoverFactory>({\n props,\n styles,\n classNames,\n });\n\n const handleOptionSubmit = (val: string) => {\n onOptionSubmit?.(val as any);\n const option = optionsLockup[val];\n\n if (multiple) {\n const currentValue = Array.isArray(_value) ? _value : [];\n if (currentValue.includes(option.value)) {\n setValue(currentValue.filter((v: any) => v !== option.value) as any);\n } else {\n setValue([...currentValue, option.value] as any);\n }\n combobox.updateSelectedOptionIndex('selected');\n } else {\n const nextValue = allowDeselect && `${option.value}` === `${_value}` ? null : option.value;\n setValue(nextValue as any);\n combobox.closeDropdown();\n }\n\n if (searchable) {\n handleSearchChange('');\n }\n };\n\n return (\n <>\n <Combobox\n store={combobox}\n __staticSelector=\"ComboboxPopover\"\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n unstyled={unstyled}\n attributes={attributes}\n onOptionSubmit={handleOptionSubmit}\n {...comboboxProps}\n {...others}\n >\n {children}\n {searchable ? (\n <SearchableDropdown\n data={parsedData as any}\n filter={filter as OptionsFilter<Primitive> | undefined}\n search={_searchValue}\n limit={limit}\n nothingFoundMessage={nothingFoundMessage}\n withScrollArea={withScrollArea}\n maxDropdownHeight={maxDropdownHeight}\n value={_value}\n checkIconPosition={checkIconPosition}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n unstyled={unstyled}\n renderOption={renderOption}\n scrollAreaProps={scrollAreaProps}\n onSearchChange={(event) => {\n handleSearchChange(event.currentTarget.value);\n }}\n />\n ) : (\n <OptionsDropdown\n data={parsedData as any}\n filter={filter as OptionsFilter<Primitive> | undefined}\n search={undefined}\n limit={limit}\n hiddenWhenEmpty={!nothingFoundMessage}\n withScrollArea={withScrollArea}\n maxDropdownHeight={maxDropdownHeight}\n filterOptions={false}\n value={_value}\n checkIconPosition={checkIconPosition}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n nothingFoundMessage={nothingFoundMessage}\n unstyled={unstyled}\n renderOption={renderOption}\n scrollAreaProps={scrollAreaProps}\n labelId={undefined}\n aria-label={undefined}\n />\n )}\n </Combobox>\n <Combobox.HiddenInput\n name={name}\n value={_value}\n form={form}\n valuesDivider={hiddenInputValuesDivider}\n {...hiddenInputProps}\n />\n </>\n );\n});\n\nComboboxPopover.classes = Combobox.classes;\nComboboxPopover.displayName = '@mantine/core/ComboboxPopover';\nComboboxPopover.Target = ComboboxPopoverTarget;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComboboxPopover.mjs","names":["comboboxClasses"],"sources":["../../../src/components/ComboboxPopover/ComboboxPopover.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport cx from 'clsx';\nimport { useUncontrolled } from '@mantine/hooks';\nimport {\n Factory,\n genericFactory,\n Primitive,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n} from '../../core';\nimport { CheckIcon } from '../Checkbox';\nimport {\n Combobox,\n ComboboxData,\n ComboboxItem,\n ComboboxLikeRenderOptionInput,\n ComboboxLikeStylesNames,\n ComboboxProps,\n defaultOptionsFilter,\n getOptionsLockup,\n getParsedComboboxData,\n isOptionsGroup,\n OptionsDropdown,\n OptionsFilter,\n useCombobox,\n} from '../Combobox';\nimport { ComboboxParsedItem } from '../Combobox/Combobox.types';\nimport { isEmptyComboboxData } from '../Combobox/OptionsDropdown/is-empty-combobox-data';\nimport { ScrollArea, ScrollAreaProps } from '../ScrollArea';\nimport { ComboboxPopoverValue } from './ComboboxPopover.types';\nimport { ComboboxPopoverTarget } from './ComboboxPopoverTarget';\nimport comboboxClasses from '../Combobox/Combobox.module.css';\n\nfunction isValueChecked(value: Primitive | Primitive[] | undefined | null, optionValue: Primitive) {\n return Array.isArray(value) ? value.includes(optionValue) : value === optionValue;\n}\n\ninterface OptionProps {\n data: ComboboxParsedItem<Primitive>;\n withCheckIcon?: boolean;\n withAlignedLabels?: boolean;\n value?: Primitive | Primitive[] | null;\n checkIconPosition?: 'left' | 'right';\n unstyled: boolean | undefined;\n renderOption?: (input: ComboboxLikeRenderOptionInput<any>) => React.ReactNode;\n}\n\nfunction Option({\n data,\n withCheckIcon,\n withAlignedLabels,\n value,\n checkIconPosition,\n unstyled,\n renderOption,\n}: OptionProps) {\n if (isOptionsGroup(data)) {\n const options = data.items.map((item) => (\n <Option\n data={item}\n value={value}\n key={`${item.value}`}\n unstyled={unstyled}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n checkIconPosition={checkIconPosition}\n renderOption={renderOption}\n />\n ));\n return <Combobox.Group label={data.group}>{options}</Combobox.Group>;\n }\n\n const checked = isValueChecked(value, data.value);\n const check =\n withCheckIcon &&\n (checked ? (\n <CheckIcon className={comboboxClasses.optionsDropdownCheckIcon} />\n ) : withAlignedLabels ? (\n <div className={comboboxClasses.optionsDropdownCheckPlaceholder} />\n ) : null);\n\n const defaultContent = (\n <>\n {checkIconPosition === 'left' && check}\n <span>{data.label}</span>\n {checkIconPosition === 'right' && check}\n </>\n );\n\n return (\n <Combobox.Option\n value={data.value}\n disabled={data.disabled}\n className={cx({ [comboboxClasses.optionsDropdownOption]: !unstyled })}\n data-reverse={checkIconPosition === 'right' || undefined}\n data-checked={checked || undefined}\n aria-selected={checked}\n active={checked}\n >\n {typeof renderOption === 'function'\n ? renderOption({ option: data, checked })\n : defaultContent}\n </Combobox.Option>\n );\n}\n\ninterface SearchableDropdownProps {\n data: ComboboxParsedItem<Primitive>[];\n filter: OptionsFilter<Primitive> | undefined;\n search: string;\n limit: number | undefined;\n nothingFoundMessage: React.ReactNode | undefined;\n withScrollArea: boolean | undefined;\n maxDropdownHeight: number | string | undefined;\n value: Primitive | Primitive[] | null;\n checkIconPosition: 'left' | 'right' | undefined;\n withCheckIcon: boolean | undefined;\n withAlignedLabels: boolean | undefined;\n unstyled: boolean | undefined;\n renderOption?: (input: ComboboxLikeRenderOptionInput<any>) => React.ReactNode;\n scrollAreaProps: ScrollAreaProps | undefined;\n onSearchChange: (event: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\nfunction SearchableDropdown({\n data,\n filter,\n search,\n limit,\n nothingFoundMessage,\n withScrollArea = true,\n maxDropdownHeight,\n value,\n checkIconPosition,\n withCheckIcon = false,\n withAlignedLabels = false,\n unstyled,\n renderOption,\n scrollAreaProps,\n onSearchChange,\n}: SearchableDropdownProps) {\n const filteredData = (filter || defaultOptionsFilter)({\n options: data,\n search,\n limit: limit ?? Infinity,\n });\n const isEmpty = isEmptyComboboxData(filteredData);\n\n const options = filteredData.map((item, index) => (\n <Option\n data={item}\n key={\n isOptionsGroup(item)\n ? `group-${typeof item.group === 'string' ? item.group : index}`\n : `${item.value}`\n }\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n value={value}\n checkIconPosition={checkIconPosition}\n unstyled={unstyled}\n renderOption={renderOption}\n />\n ));\n\n return (\n <Combobox.Dropdown data-composed>\n <Combobox.Search value={search} onChange={onSearchChange} placeholder=\"Search...\" />\n <Combobox.Options>\n {withScrollArea ? (\n <ScrollArea.Autosize\n mah={maxDropdownHeight ?? 220}\n type=\"scroll\"\n scrollbarSize=\"var(--combobox-padding)\"\n offsetScrollbars=\"y\"\n {...scrollAreaProps}\n >\n {options}\n </ScrollArea.Autosize>\n ) : (\n options\n )}\n {isEmpty && nothingFoundMessage && <Combobox.Empty>{nothingFoundMessage}</Combobox.Empty>}\n </Combobox.Options>\n </Combobox.Dropdown>\n );\n}\n\nexport type ComboboxPopoverStylesNames = ComboboxLikeStylesNames | 'search';\n\nexport interface ComboboxPopoverProps<\n Multiple extends boolean = false,\n Value extends Primitive = string,\n> extends StylesApiProps<ComboboxPopoverFactory> {\n /** If set, multiple items can be selected at the same time */\n multiple?: Multiple;\n\n /** Controlled component value */\n value?: ComboboxPopoverValue<Multiple, Value>;\n\n /** Uncontrolled component default value */\n defaultValue?: ComboboxPopoverValue<Multiple, Value>;\n\n /** Called when value changes */\n onChange?: (value: ComboboxPopoverValue<Multiple, Value>) => void;\n\n /** Data used to generate options */\n data?: ComboboxData<Value>;\n\n /** Controlled dropdown opened state */\n dropdownOpened?: boolean;\n\n /** Uncontrolled dropdown initial opened state */\n defaultDropdownOpened?: boolean;\n\n /** Called when dropdown opens */\n onDropdownOpen?: () => void;\n\n /** Called when dropdown closes */\n onDropdownClose?: () => void;\n\n /** Called when option is submitted from dropdown with mouse click or Enter key */\n onOptionSubmit?: (value: Value) => void;\n\n /** Props passed down to Combobox component */\n comboboxProps?: ComboboxProps;\n\n /** Function based on which items are filtered and sorted */\n filter?: OptionsFilter<Value>;\n\n /** Maximum number of options displayed at a time @default Infinity */\n limit?: number;\n\n /** Determines whether the options should be wrapped with ScrollArea.AutoSize @default true */\n withScrollArea?: boolean;\n\n /** max-height of the dropdown @default 220 */\n maxDropdownHeight?: number | string;\n\n /** If set, the first option is selected when dropdown opens @default false */\n selectFirstOptionOnDropdownOpen?: boolean;\n\n /** Displays check icon near the selected option label @default true */\n withCheckIcon?: boolean;\n\n /** Aligns unchecked labels with the checked one @default false */\n withAlignedLabels?: boolean;\n\n /** Position of the check icon relative to the option label @default 'left' */\n checkIconPosition?: 'left' | 'right';\n\n /** Message displayed when no options match the search query or when there is no data */\n nothingFoundMessage?: React.ReactNode;\n\n /** Allows searching through options @default false */\n searchable?: boolean;\n\n /** Controlled search value */\n searchValue?: string;\n\n /** Default search value */\n defaultSearchValue?: string;\n\n /** Called when search changes */\n onSearchChange?: (value: string) => void;\n\n /** Allows deselecting the selected option by clicking it (only for single mode) @default true */\n allowDeselect?: boolean;\n\n /** A function to render content of the option, replaces the default content of the option */\n renderOption?: (item: ComboboxLikeRenderOptionInput<ComboboxItem>) => React.ReactNode;\n\n /** Props passed down to the underlying ScrollArea component in the dropdown */\n scrollAreaProps?: ScrollAreaProps;\n\n /** Props passed down to the hidden input */\n hiddenInputProps?: Omit<React.ComponentProps<'input'>, 'value'>;\n\n /** Hidden input name for form submission */\n name?: string;\n\n /** Hidden input form for form submission */\n form?: string;\n\n /** Content of the component */\n children?: React.ReactNode;\n\n /** Divider used to separate values in the hidden input value attribute @default ',' */\n hiddenInputValuesDivider?: string;\n}\n\nexport type ComboboxPopoverFactory = Factory<{\n props: ComboboxPopoverProps;\n ref: HTMLDivElement;\n stylesNames: ComboboxPopoverStylesNames;\n signature: <Multiple extends boolean = false, Value extends Primitive = string>(\n props: ComboboxPopoverProps<Multiple, Value>\n ) => React.JSX.Element;\n staticComponents: {\n Target: typeof ComboboxPopoverTarget;\n };\n}>;\n\nconst defaultProps = {\n withCheckIcon: true,\n allowDeselect: true,\n checkIconPosition: 'left',\n hiddenInputValuesDivider: ',',\n} satisfies Partial<ComboboxPopoverProps>;\n\nexport const ComboboxPopover = genericFactory<ComboboxPopoverFactory>((_props) => {\n const props = useProps('ComboboxPopover', defaultProps as any, _props);\n const {\n classNames,\n styles,\n unstyled,\n vars,\n children,\n multiple,\n value,\n defaultValue,\n onChange,\n data,\n dropdownOpened,\n defaultDropdownOpened,\n onDropdownOpen,\n onDropdownClose,\n onOptionSubmit,\n comboboxProps,\n filter,\n limit,\n withScrollArea,\n maxDropdownHeight,\n selectFirstOptionOnDropdownOpen,\n withCheckIcon,\n withAlignedLabels,\n checkIconPosition,\n nothingFoundMessage,\n searchable,\n searchValue,\n defaultSearchValue,\n onSearchChange,\n allowDeselect,\n renderOption,\n scrollAreaProps,\n hiddenInputProps,\n name,\n form,\n hiddenInputValuesDivider,\n attributes,\n ...others\n } = props;\n\n const parsedData = useMemo(() => getParsedComboboxData(data), [data]);\n const optionsLockup = useMemo(() => getOptionsLockup(parsedData), [parsedData]);\n\n const [_value, setValue] = useUncontrolled({\n value,\n defaultValue,\n finalValue: multiple ? ([] as any) : null,\n onChange,\n });\n\n const [_searchValue, setSearchValue] = useUncontrolled({\n value: searchValue,\n defaultValue: defaultSearchValue,\n finalValue: '',\n onChange: onSearchChange,\n });\n\n const combobox = useCombobox({\n opened: dropdownOpened,\n defaultOpened: defaultDropdownOpened,\n onDropdownOpen: () => {\n onDropdownOpen?.();\n if (searchable) {\n combobox.focusSearchInput();\n }\n if (selectFirstOptionOnDropdownOpen) {\n combobox.selectFirstOption();\n }\n },\n onDropdownClose: () => {\n onDropdownClose?.();\n combobox.resetSelectedOption();\n },\n });\n\n const handleSearchChange = (val: string) => {\n setSearchValue(val);\n combobox.resetSelectedOption();\n };\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<ComboboxPopoverFactory>({\n props,\n styles,\n classNames,\n });\n\n const handleOptionSubmit = (val: string) => {\n onOptionSubmit?.(val as any);\n const option = optionsLockup[val];\n\n if (multiple) {\n const currentValue = Array.isArray(_value) ? _value : [];\n if (currentValue.includes(option.value)) {\n setValue(currentValue.filter((v: any) => v !== option.value) as any);\n } else {\n setValue([...currentValue, option.value] as any);\n }\n combobox.updateSelectedOptionIndex('selected');\n } else {\n const nextValue = allowDeselect && `${option.value}` === `${_value}` ? null : option.value;\n setValue(nextValue as any);\n combobox.closeDropdown();\n }\n\n if (searchable) {\n handleSearchChange('');\n }\n };\n\n return (\n <>\n <Combobox\n store={combobox}\n __staticSelector=\"ComboboxPopover\"\n classNames={resolvedClassNames}\n styles={resolvedStyles}\n unstyled={unstyled}\n attributes={attributes}\n onOptionSubmit={handleOptionSubmit}\n returnFocus\n {...comboboxProps}\n {...others}\n >\n {children}\n {searchable ? (\n <SearchableDropdown\n data={parsedData as any}\n filter={filter as OptionsFilter<Primitive> | undefined}\n search={_searchValue}\n limit={limit}\n nothingFoundMessage={nothingFoundMessage}\n withScrollArea={withScrollArea}\n maxDropdownHeight={maxDropdownHeight}\n value={_value}\n checkIconPosition={checkIconPosition}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n unstyled={unstyled}\n renderOption={renderOption}\n scrollAreaProps={scrollAreaProps}\n onSearchChange={(event) => {\n handleSearchChange(event.currentTarget.value);\n }}\n />\n ) : (\n <OptionsDropdown\n data={parsedData as any}\n filter={filter as OptionsFilter<Primitive> | undefined}\n search={undefined}\n limit={limit}\n hiddenWhenEmpty={!nothingFoundMessage}\n withScrollArea={withScrollArea}\n maxDropdownHeight={maxDropdownHeight}\n filterOptions={false}\n value={_value}\n checkIconPosition={checkIconPosition}\n withCheckIcon={withCheckIcon}\n withAlignedLabels={withAlignedLabels}\n nothingFoundMessage={nothingFoundMessage}\n unstyled={unstyled}\n renderOption={renderOption}\n scrollAreaProps={scrollAreaProps}\n labelId={undefined}\n aria-label={undefined}\n />\n )}\n </Combobox>\n <Combobox.HiddenInput\n name={name}\n value={_value}\n form={form}\n valuesDivider={hiddenInputValuesDivider}\n {...hiddenInputProps}\n />\n </>\n );\n});\n\nComboboxPopover.classes = Combobox.classes;\nComboboxPopover.displayName = '@mantine/core/ComboboxPopover';\nComboboxPopover.Target = ComboboxPopoverTarget;\n"],"mappings":"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"}
|
|
@@ -117,7 +117,7 @@ const InputWrapper = factory((_props) => {
|
|
|
117
117
|
getStyles,
|
|
118
118
|
describedBy,
|
|
119
119
|
inputId,
|
|
120
|
-
labelId,
|
|
120
|
+
labelId: _label && inputWrapperOrder.includes("label") ? labelId : void 0,
|
|
121
121
|
...getInputOffsets(inputWrapperOrder, {
|
|
122
122
|
hasDescription,
|
|
123
123
|
hasError: hasError || hasSuccess
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputWrapper.mjs","names":["useId","classes"],"sources":["../../../../src/components/Input/InputWrapper/InputWrapper.tsx"],"sourcesContent":["import { Fragment } from 'react';\nimport { useId } from '@mantine/hooks';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getFontSize,\n MantineFontSize,\n PlaceholderPolymorphicProps,\n rem,\n StylesApiProps,\n useProps,\n useStyles,\n} from '../../../core';\nimport {\n InputDescription,\n InputDescriptionCssVariables,\n InputDescriptionProps,\n InputDescriptionStylesNames,\n} from '../InputDescription/InputDescription';\nimport {\n InputError,\n InputErrorCssVariables,\n InputErrorProps,\n InputErrorStylesNames,\n} from '../InputError/InputError';\nimport {\n InputLabel,\n InputLabelCssVariables,\n InputLabelProps,\n InputLabelStylesNames,\n} from '../InputLabel/InputLabel';\nimport {\n InputSuccess,\n InputSuccessCssVariables,\n InputSuccessProps,\n InputSuccessStylesNames,\n} from '../InputSuccess/InputSuccess';\nimport { InputWrapperContext } from '../InputWrapper.context';\nimport { getInputOffsets } from './get-input-offsets/get-input-offsets';\nimport classes from '../Input.module.css';\n\nexport type InputWrapperCssVariables = InputLabelCssVariables &\n InputErrorCssVariables &\n InputSuccessCssVariables &\n InputDescriptionCssVariables;\n\nexport type InputWrapperStylesNames =\n | 'root'\n | InputLabelStylesNames\n | InputDescriptionStylesNames\n | InputErrorStylesNames\n | InputSuccessStylesNames;\n\nexport interface __InputWrapperProps {\n /** Contents of `Input.Label` component. If not set, label is not displayed. */\n label?: React.ReactNode;\n\n /** Contents of `Input.Description` component. If not set, description is not displayed. */\n description?: React.ReactNode;\n\n /** Contents of `Input.Error` component. If not set, error is not displayed. */\n error?: React.ReactNode;\n\n /** Contents of `Input.Success` component. If not set, success is not displayed. */\n success?: React.ReactNode;\n\n /** Adds required attribute to the input and a red asterisk on the right side of label @default false */\n required?: boolean;\n\n /** If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. @default false */\n withAsterisk?: boolean;\n\n /** Props passed down to the `Input.Label` component */\n labelProps?: InputLabelProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Description` component */\n descriptionProps?: InputDescriptionProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Error` component */\n errorProps?: InputErrorProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Success` component */\n successProps?: InputSuccessProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. @default React.Fragment */\n inputContainer?: (children: React.ReactNode) => React.ReactNode;\n\n /** Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. @default ['label', 'description', 'input', 'error'] */\n inputWrapperOrder?: ('label' | 'input' | 'description' | 'error')[];\n}\n\nexport interface InputWrapperProps\n extends __InputWrapperProps, BoxProps, StylesApiProps<InputWrapperFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Props passed to Styles API context, replaces Input.Wrapper props */\n __stylesApiProps?: Record<string, any>;\n\n /** Static id used as base to generate `aria-` attributes, by default generates random id */\n id?: string;\n\n /** Controls size of `Input.Label`, `Input.Description` and `Input.Error` components */\n size?: MantineFontSize;\n\n /** Root element for the label. Use `'div'` when wrapper contains multiple input elements and you need to handle `htmlFor` manually. @default 'label' */\n labelElement?: 'label' | 'div';\n}\n\nexport type InputWrapperFactory = Factory<{\n props: InputWrapperProps;\n ref: HTMLDivElement;\n stylesNames: InputWrapperStylesNames;\n vars: InputWrapperCssVariables;\n}>;\n\nconst defaultProps = {\n labelElement: 'label',\n inputContainer: (children) => children,\n inputWrapperOrder: ['label', 'description', 'input', 'error'],\n} satisfies Partial<InputWrapperProps>;\n\nconst varsResolver = createVarsResolver<InputWrapperFactory>((_, { size }) => ({\n label: {\n '--input-label-size': getFontSize(size),\n '--input-asterisk-color': undefined,\n },\n\n error: {\n '--input-error-size': size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n\n success: {\n '--input-success-size':\n size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n\n description: {\n '--input-description-size':\n size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n}));\n\nexport const InputWrapper = factory<InputWrapperFactory>((_props) => {\n const props = useProps('InputWrapper', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n size,\n variant,\n __staticSelector,\n inputContainer,\n inputWrapperOrder,\n label,\n error,\n success,\n description,\n labelProps,\n descriptionProps,\n errorProps,\n successProps,\n labelElement,\n children,\n withAsterisk,\n id,\n required,\n __stylesApiProps,\n mod,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<InputWrapperFactory>({\n name: ['InputWrapper', __staticSelector],\n props: __stylesApiProps || props,\n classes,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const sharedProps = {\n size,\n variant,\n __staticSelector,\n };\n\n const idBase = useId(id);\n const isRequired = typeof withAsterisk === 'boolean' ? withAsterisk : required;\n const errorId = errorProps?.id || `${idBase}-error`;\n const successId = successProps?.id || `${idBase}-success`;\n const descriptionId = descriptionProps?.id || `${idBase}-description`;\n const inputId = idBase;\n const hasError = !!error && typeof error !== 'boolean';\n const hasSuccess = !!success && typeof success !== 'boolean' && !error;\n const hasDescription = !!description;\n const errorRendered = hasError && inputWrapperOrder.includes('error');\n const successRendered = hasSuccess && inputWrapperOrder.includes('error');\n const descriptionRendered = hasDescription && inputWrapperOrder.includes('description');\n const _describedBy = `${errorRendered ? errorId : ''} ${successRendered ? successId : ''} ${descriptionRendered ? descriptionId : ''}`;\n const describedBy = _describedBy.trim().length > 0 ? _describedBy.trim() : undefined;\n const labelId = labelProps?.id || `${idBase}-label`;\n\n const _label = label && (\n <InputLabel\n key=\"label\"\n labelElement={labelElement}\n id={labelId}\n htmlFor={inputId}\n required={isRequired}\n {...sharedProps}\n {...labelProps}\n >\n {label}\n </InputLabel>\n );\n\n const _description = hasDescription && (\n <InputDescription\n key=\"description\"\n {...descriptionProps}\n {...sharedProps}\n size={descriptionProps?.size || sharedProps.size}\n id={descriptionProps?.id || descriptionId}\n >\n {description}\n </InputDescription>\n );\n\n const _input = <Fragment key=\"input\">{inputContainer(children)}</Fragment>;\n\n const _error = hasError && (\n <InputError\n {...errorProps}\n {...sharedProps}\n size={errorProps?.size || sharedProps.size}\n key=\"error\"\n id={errorProps?.id || errorId}\n >\n {error}\n </InputError>\n );\n\n const _success = hasSuccess && (\n <InputSuccess\n {...successProps}\n {...sharedProps}\n size={successProps?.size || sharedProps.size}\n key=\"success\"\n id={successProps?.id || successId}\n >\n {success}\n </InputSuccess>\n );\n\n const content = inputWrapperOrder.map((part) => {\n switch (part) {\n case 'label':\n return _label;\n case 'input':\n return _input;\n case 'description':\n return _description;\n case 'error':\n return _error || _success;\n default:\n return null;\n }\n });\n\n return (\n <InputWrapperContext\n value={{\n getStyles,\n describedBy,\n inputId,\n labelId,\n ...getInputOffsets(inputWrapperOrder, { hasDescription, hasError: hasError || hasSuccess }),\n }}\n >\n <Box\n variant={variant}\n size={size}\n mod={[{ error: !!error, success: !!success && !error }, mod]}\n id={labelElement === 'label' ? undefined : id}\n {...getStyles('root')}\n {...others}\n >\n {content}\n </Box>\n </InputWrapperContext>\n );\n});\n\nInputWrapper.classes = classes;\nInputWrapper.varsResolver = varsResolver;\nInputWrapper.displayName = '@mantine/core/InputWrapper';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputWrapper.mjs","names":["useId","classes"],"sources":["../../../../src/components/Input/InputWrapper/InputWrapper.tsx"],"sourcesContent":["import { Fragment } from 'react';\nimport { useId } from '@mantine/hooks';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getFontSize,\n MantineFontSize,\n PlaceholderPolymorphicProps,\n rem,\n StylesApiProps,\n useProps,\n useStyles,\n} from '../../../core';\nimport {\n InputDescription,\n InputDescriptionCssVariables,\n InputDescriptionProps,\n InputDescriptionStylesNames,\n} from '../InputDescription/InputDescription';\nimport {\n InputError,\n InputErrorCssVariables,\n InputErrorProps,\n InputErrorStylesNames,\n} from '../InputError/InputError';\nimport {\n InputLabel,\n InputLabelCssVariables,\n InputLabelProps,\n InputLabelStylesNames,\n} from '../InputLabel/InputLabel';\nimport {\n InputSuccess,\n InputSuccessCssVariables,\n InputSuccessProps,\n InputSuccessStylesNames,\n} from '../InputSuccess/InputSuccess';\nimport { InputWrapperContext } from '../InputWrapper.context';\nimport { getInputOffsets } from './get-input-offsets/get-input-offsets';\nimport classes from '../Input.module.css';\n\nexport type InputWrapperCssVariables = InputLabelCssVariables &\n InputErrorCssVariables &\n InputSuccessCssVariables &\n InputDescriptionCssVariables;\n\nexport type InputWrapperStylesNames =\n | 'root'\n | InputLabelStylesNames\n | InputDescriptionStylesNames\n | InputErrorStylesNames\n | InputSuccessStylesNames;\n\nexport interface __InputWrapperProps {\n /** Contents of `Input.Label` component. If not set, label is not displayed. */\n label?: React.ReactNode;\n\n /** Contents of `Input.Description` component. If not set, description is not displayed. */\n description?: React.ReactNode;\n\n /** Contents of `Input.Error` component. If not set, error is not displayed. */\n error?: React.ReactNode;\n\n /** Contents of `Input.Success` component. If not set, success is not displayed. */\n success?: React.ReactNode;\n\n /** Adds required attribute to the input and a red asterisk on the right side of label @default false */\n required?: boolean;\n\n /** If set, the required asterisk is displayed next to the label. Overrides `required` prop. Does not add required attribute to the input. @default false */\n withAsterisk?: boolean;\n\n /** Props passed down to the `Input.Label` component */\n labelProps?: InputLabelProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Description` component */\n descriptionProps?: InputDescriptionProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Error` component */\n errorProps?: InputErrorProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Props passed down to the `Input.Success` component */\n successProps?: InputSuccessProps & DataAttributes & PlaceholderPolymorphicProps;\n\n /** Render function to wrap the input element. Useful for adding tooltips, popovers, or other wrappers around the input. @default React.Fragment */\n inputContainer?: (children: React.ReactNode) => React.ReactNode;\n\n /** Controls order and visibility of wrapper elements. Only elements included in this array will be rendered. @default ['label', 'description', 'input', 'error'] */\n inputWrapperOrder?: ('label' | 'input' | 'description' | 'error')[];\n}\n\nexport interface InputWrapperProps\n extends __InputWrapperProps, BoxProps, StylesApiProps<InputWrapperFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Props passed to Styles API context, replaces Input.Wrapper props */\n __stylesApiProps?: Record<string, any>;\n\n /** Static id used as base to generate `aria-` attributes, by default generates random id */\n id?: string;\n\n /** Controls size of `Input.Label`, `Input.Description` and `Input.Error` components */\n size?: MantineFontSize;\n\n /** Root element for the label. Use `'div'` when wrapper contains multiple input elements and you need to handle `htmlFor` manually. @default 'label' */\n labelElement?: 'label' | 'div';\n}\n\nexport type InputWrapperFactory = Factory<{\n props: InputWrapperProps;\n ref: HTMLDivElement;\n stylesNames: InputWrapperStylesNames;\n vars: InputWrapperCssVariables;\n}>;\n\nconst defaultProps = {\n labelElement: 'label',\n inputContainer: (children) => children,\n inputWrapperOrder: ['label', 'description', 'input', 'error'],\n} satisfies Partial<InputWrapperProps>;\n\nconst varsResolver = createVarsResolver<InputWrapperFactory>((_, { size }) => ({\n label: {\n '--input-label-size': getFontSize(size),\n '--input-asterisk-color': undefined,\n },\n\n error: {\n '--input-error-size': size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n\n success: {\n '--input-success-size':\n size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n\n description: {\n '--input-description-size':\n size === undefined ? undefined : `calc(${getFontSize(size)} - ${rem(2)})`,\n },\n}));\n\nexport const InputWrapper = factory<InputWrapperFactory>((_props) => {\n const props = useProps('InputWrapper', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n size,\n variant,\n __staticSelector,\n inputContainer,\n inputWrapperOrder,\n label,\n error,\n success,\n description,\n labelProps,\n descriptionProps,\n errorProps,\n successProps,\n labelElement,\n children,\n withAsterisk,\n id,\n required,\n __stylesApiProps,\n mod,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<InputWrapperFactory>({\n name: ['InputWrapper', __staticSelector],\n props: __stylesApiProps || props,\n classes,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const sharedProps = {\n size,\n variant,\n __staticSelector,\n };\n\n const idBase = useId(id);\n const isRequired = typeof withAsterisk === 'boolean' ? withAsterisk : required;\n const errorId = errorProps?.id || `${idBase}-error`;\n const successId = successProps?.id || `${idBase}-success`;\n const descriptionId = descriptionProps?.id || `${idBase}-description`;\n const inputId = idBase;\n const hasError = !!error && typeof error !== 'boolean';\n const hasSuccess = !!success && typeof success !== 'boolean' && !error;\n const hasDescription = !!description;\n const errorRendered = hasError && inputWrapperOrder.includes('error');\n const successRendered = hasSuccess && inputWrapperOrder.includes('error');\n const descriptionRendered = hasDescription && inputWrapperOrder.includes('description');\n const _describedBy = `${errorRendered ? errorId : ''} ${successRendered ? successId : ''} ${descriptionRendered ? descriptionId : ''}`;\n const describedBy = _describedBy.trim().length > 0 ? _describedBy.trim() : undefined;\n const labelId = labelProps?.id || `${idBase}-label`;\n\n const _label = label && (\n <InputLabel\n key=\"label\"\n labelElement={labelElement}\n id={labelId}\n htmlFor={inputId}\n required={isRequired}\n {...sharedProps}\n {...labelProps}\n >\n {label}\n </InputLabel>\n );\n\n const _description = hasDescription && (\n <InputDescription\n key=\"description\"\n {...descriptionProps}\n {...sharedProps}\n size={descriptionProps?.size || sharedProps.size}\n id={descriptionProps?.id || descriptionId}\n >\n {description}\n </InputDescription>\n );\n\n const _input = <Fragment key=\"input\">{inputContainer(children)}</Fragment>;\n\n const _error = hasError && (\n <InputError\n {...errorProps}\n {...sharedProps}\n size={errorProps?.size || sharedProps.size}\n key=\"error\"\n id={errorProps?.id || errorId}\n >\n {error}\n </InputError>\n );\n\n const _success = hasSuccess && (\n <InputSuccess\n {...successProps}\n {...sharedProps}\n size={successProps?.size || sharedProps.size}\n key=\"success\"\n id={successProps?.id || successId}\n >\n {success}\n </InputSuccess>\n );\n\n const content = inputWrapperOrder.map((part) => {\n switch (part) {\n case 'label':\n return _label;\n case 'input':\n return _input;\n case 'description':\n return _description;\n case 'error':\n return _error || _success;\n default:\n return null;\n }\n });\n\n return (\n <InputWrapperContext\n value={{\n getStyles,\n describedBy,\n inputId,\n labelId: _label && inputWrapperOrder.includes('label') ? labelId : undefined,\n ...getInputOffsets(inputWrapperOrder, { hasDescription, hasError: hasError || hasSuccess }),\n }}\n >\n <Box\n variant={variant}\n size={size}\n mod={[{ error: !!error, success: !!success && !error }, mod]}\n id={labelElement === 'label' ? undefined : id}\n {...getStyles('root')}\n {...others}\n >\n {content}\n </Box>\n </InputWrapperContext>\n );\n});\n\nInputWrapper.classes = classes;\nInputWrapper.varsResolver = varsResolver;\nInputWrapper.displayName = '@mantine/core/InputWrapper';\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Marquee.mjs","names":["classes"],"sources":["../../../src/components/Marquee/Marquee.tsx"],"sourcesContent":["import {\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n factory,\n Factory,\n getSpacing,\n MantineSpacing,\n StylesApiProps,\n useProps,\n useStyles,\n} from '../../core';\nimport classes from './Marquee.module.css';\n\nexport type MarqueeStylesNames = 'root' | 'content' | 'group';\nexport type MarqueeCssVariables = {\n root:\n | '--marquee-duration'\n | '--marquee-gap'\n | '--marquee-repeat'\n | '--marquee-fade-color'\n | '--marquee-fade-size';\n};\n\nexport interface MarqueeProps\n extends BoxProps, StylesApiProps<MarqueeFactory>, ElementProps<'div'> {\n /** Reverses animation direction @default false */\n reverse?: boolean;\n\n /** Pauses animation on hover @default false */\n pauseOnHover?: boolean;\n\n /** Content to scroll */\n children: React.ReactNode;\n\n /** Scroll orientation @default 'horizontal' */\n orientation?: 'horizontal' | 'vertical';\n\n /** Number of times children are repeated inline for seamless scrolling @default 4 */\n repeat?: number;\n\n /** Animation duration in ms @default
|
|
1
|
+
{"version":3,"file":"Marquee.mjs","names":["classes"],"sources":["../../../src/components/Marquee/Marquee.tsx"],"sourcesContent":["import {\n Box,\n BoxProps,\n createVarsResolver,\n ElementProps,\n factory,\n Factory,\n getSpacing,\n MantineSpacing,\n StylesApiProps,\n useProps,\n useStyles,\n} from '../../core';\nimport classes from './Marquee.module.css';\n\nexport type MarqueeStylesNames = 'root' | 'content' | 'group';\nexport type MarqueeCssVariables = {\n root:\n | '--marquee-duration'\n | '--marquee-gap'\n | '--marquee-repeat'\n | '--marquee-fade-color'\n | '--marquee-fade-size';\n};\n\nexport interface MarqueeProps\n extends BoxProps, StylesApiProps<MarqueeFactory>, ElementProps<'div'> {\n /** Reverses animation direction @default false */\n reverse?: boolean;\n\n /** Pauses animation on hover @default false */\n pauseOnHover?: boolean;\n\n /** Content to scroll */\n children: React.ReactNode;\n\n /** Scroll orientation @default 'horizontal' */\n orientation?: 'horizontal' | 'vertical';\n\n /** Number of times children are repeated inline for seamless scrolling @default 4 */\n repeat?: number;\n\n /** Animation duration in ms @default 100000 */\n duration?: number;\n\n /** Gap between repeated children, key of `theme.spacing` or any valid CSS value @default 'md' */\n gap?: MantineSpacing;\n\n /** Whether to show gradient fade on edges, @default true */\n fadeEdges?: boolean;\n\n /** Color of the fade gradient, @default 'var(--mantine-color-body)' */\n fadeEdgeColor?: string;\n\n /** Size of the fade gradient, @default '5%' */\n fadeEdgeSize?: string;\n}\n\nexport type MarqueeFactory = Factory<{\n props: MarqueeProps;\n ref: HTMLDivElement;\n stylesNames: MarqueeStylesNames;\n vars: MarqueeCssVariables;\n}>;\n\nconst defaultProps = {\n repeat: 4,\n duration: 100_000,\n orientation: 'horizontal',\n fadeEdges: true,\n} satisfies Partial<MarqueeProps>;\n\nconst varsResolver = createVarsResolver<MarqueeFactory>(\n (_, { duration, gap, repeat, fadeEdgeColor, fadeEdgeSize }) => ({\n root: {\n '--marquee-duration': `${duration}ms`,\n '--marquee-gap': getSpacing(gap),\n '--marquee-repeat': (repeat ?? 4).toString(),\n '--marquee-fade-color': fadeEdgeColor,\n '--marquee-fade-size': fadeEdgeSize,\n },\n })\n);\n\nexport const Marquee = factory<MarqueeFactory>((_props) => {\n const props = useProps('Marquee', defaultProps, _props);\n const {\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n children,\n reverse,\n pauseOnHover,\n orientation,\n repeat,\n duration,\n gap,\n fadeEdges,\n fadeEdgeColor,\n fadeEdgeSize,\n mod,\n attributes,\n ...others\n } = props;\n\n const getStyles = useStyles<MarqueeFactory>({\n name: 'Marquee',\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n attributes,\n vars,\n varsResolver,\n });\n\n const repeatedChildren = Array(repeat)\n .fill(0)\n .map((_, index) => (\n <div key={index} {...getStyles('group')}>\n {children}\n </div>\n ));\n\n return (\n <Box\n {...getStyles('root')}\n mod={[{ orientation, reverse, pauseOnHover, 'fade-edges': fadeEdges }, mod]}\n {...others}\n >\n <div {...getStyles('content')}>{repeatedChildren}</div>\n </Box>\n );\n});\n\nMarquee.classes = classes;\nMarquee.varsResolver = varsResolver;\nMarquee.displayName = '@mantine/core/Marquee';\n\nexport namespace Marquee {\n export type Props = MarqueeProps;\n export type StylesNames = MarqueeStylesNames;\n export type CssVariables = MarqueeCssVariables;\n export type Factory = MarqueeFactory;\n}\n"],"mappings":";;;;;;;;;;AAiEA,MAAM,eAAe;CACnB,QAAQ;CACR,UAAU;CACV,aAAa;CACb,WAAW;AACb;AAEA,MAAM,eAAe,oBAClB,GAAG,EAAE,UAAU,KAAK,QAAQ,eAAe,oBAAoB,EAC9D,MAAM;CACJ,sBAAsB,GAAG,SAAS;CAClC,iBAAiB,WAAW,GAAG;CAC/B,qBAAqB,UAAU,EAAA,CAAG,SAAS;CAC3C,wBAAwB;CACxB,uBAAuB;AACzB,EACF,EACF;AAEA,MAAa,UAAU,SAAyB,WAAW;CACzD,MAAM,QAAQ,SAAS,WAAW,cAAc,MAAM;CACtD,MAAM,EACJ,YACA,WACA,OACA,QACA,UACA,MACA,UACA,SACA,cACA,aACA,QACA,UACA,KACA,WACA,eACA,cACA,KACA,YACA,GAAG,WACD;CAEJ,MAAM,YAAY,UAA0B;EAC1C,MAAM;EACN,SAAA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,mBAAmB,MAAM,MAAM,CAAC,CACnC,KAAK,CAAC,CAAC,CACP,KAAK,GAAG,UACP,oBAAC,OAAD;EAAiB,GAAI,UAAU,OAAO;EACnC;CACE,GAFK,KAEL,CACN;CAEH,OACE,oBAAC,KAAD;EACE,GAAI,UAAU,MAAM;EACpB,KAAK,CAAC;GAAE;GAAa;GAAS;GAAc,cAAc;EAAU,GAAG,GAAG;EAC1E,GAAI;EAEJ,UAAA,oBAAC,OAAD;GAAK,GAAI,UAAU,SAAS;GAAI,UAAA;EAAsB,CAAA;CACnD,CAAA;AAET,CAAC;AAED,QAAQ,UAAUA;AAClB,QAAQ,eAAe;AACvB,QAAQ,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Marquee.module.mjs","names":[],"sources":["../../../src/components/Marquee/Marquee.module.css"],"sourcesContent":["@keyframes marquee-horizontal {\n from {\n transform: translateX(0);\n }\n\n to {\n transform: translateX(\n calc(\n -100% / var(--marquee-repeat, 4) - var(--marquee-gap, var(--mantine-spacing-md)) /\n var(--marquee-repeat, 4)\n )\n );\n }\n}\n\n@keyframes marquee-vertical {\n from {\n transform: translateY(0);\n }\n\n to {\n transform: translateY(\n calc(\n -100% / var(--marquee-repeat, 4) - var(--marquee-gap, var(--mantine-spacing-md)) /\n var(--marquee-repeat, 4)\n )\n );\n }\n}\n\n.root {\n --_fade-color: var(--marquee-fade-color, var(--mantine-color-body));\n --_fade-size: var(--marquee-fade-size, 5%);\n\n position: relative;\n overflow: hidden;\n display: flex;\n max-height: 100%;\n max-width: 100%;\n\n &:where([data-orientation='horizontal']) {\n flex-direction: row;\n }\n\n &:where([data-orientation='vertical']) {\n flex-direction: column;\n }\n\n /* Fade edges using pseudo-elements */\n &[data-fade-edges]::before,\n &[data-fade-edges]::after {\n content: '';\n position: absolute;\n z-index: 1;\n pointer-events: none;\n }\n\n /* Horizontal fade edges */\n &[data-orientation='horizontal'][data-fade-edges]::before,\n &[data-orientation='horizontal'][data-fade-edges]::after {\n top: 0;\n bottom: 0;\n width: var(--_fade-size);\n }\n\n &[data-orientation='horizontal'][data-fade-edges]::before {\n left: 0;\n background: linear-gradient(to right, var(--_fade-color), transparent);\n }\n\n &[data-orientation='horizontal'][data-fade-edges]::after {\n right: 0;\n background: linear-gradient(to left, var(--_fade-color), transparent);\n }\n\n /* Vertical fade edges */\n &[data-orientation='vertical'][data-fade-edges]::before,\n &[data-orientation='vertical'][data-fade-edges]::after {\n left: 0;\n right: 0;\n height: var(--_fade-size);\n }\n\n &[data-orientation='vertical'][data-fade-edges]::before {\n top: 0;\n background: linear-gradient(to bottom, var(--_fade-color), transparent);\n }\n\n &[data-orientation='vertical'][data-fade-edges]::after {\n bottom: 0;\n background: linear-gradient(to top, var(--_fade-color), transparent);\n }\n}\n\n.content {\n display: flex;\n gap: var(--marquee-gap, var(--mantine-spacing-md));\n animation-duration: var(--marquee-duration,
|
|
1
|
+
{"version":3,"file":"Marquee.module.mjs","names":[],"sources":["../../../src/components/Marquee/Marquee.module.css"],"sourcesContent":["@keyframes marquee-horizontal {\n from {\n transform: translateX(0);\n }\n\n to {\n transform: translateX(\n calc(\n -100% / var(--marquee-repeat, 4) - var(--marquee-gap, var(--mantine-spacing-md)) /\n var(--marquee-repeat, 4)\n )\n );\n }\n}\n\n@keyframes marquee-vertical {\n from {\n transform: translateY(0);\n }\n\n to {\n transform: translateY(\n calc(\n -100% / var(--marquee-repeat, 4) - var(--marquee-gap, var(--mantine-spacing-md)) /\n var(--marquee-repeat, 4)\n )\n );\n }\n}\n\n.root {\n --_fade-color: var(--marquee-fade-color, var(--mantine-color-body));\n --_fade-size: var(--marquee-fade-size, 5%);\n\n position: relative;\n overflow: hidden;\n display: flex;\n max-height: 100%;\n max-width: 100%;\n\n &:where([data-orientation='horizontal']) {\n flex-direction: row;\n }\n\n &:where([data-orientation='vertical']) {\n flex-direction: column;\n }\n\n /* Fade edges using pseudo-elements */\n &[data-fade-edges]::before,\n &[data-fade-edges]::after {\n content: '';\n position: absolute;\n z-index: 1;\n pointer-events: none;\n }\n\n /* Horizontal fade edges */\n &[data-orientation='horizontal'][data-fade-edges]::before,\n &[data-orientation='horizontal'][data-fade-edges]::after {\n top: 0;\n bottom: 0;\n width: var(--_fade-size);\n }\n\n &[data-orientation='horizontal'][data-fade-edges]::before {\n left: 0;\n background: linear-gradient(to right, var(--_fade-color), transparent);\n }\n\n &[data-orientation='horizontal'][data-fade-edges]::after {\n right: 0;\n background: linear-gradient(to left, var(--_fade-color), transparent);\n }\n\n /* Vertical fade edges */\n &[data-orientation='vertical'][data-fade-edges]::before,\n &[data-orientation='vertical'][data-fade-edges]::after {\n left: 0;\n right: 0;\n height: var(--_fade-size);\n }\n\n &[data-orientation='vertical'][data-fade-edges]::before {\n top: 0;\n background: linear-gradient(to bottom, var(--_fade-color), transparent);\n }\n\n &[data-orientation='vertical'][data-fade-edges]::after {\n bottom: 0;\n background: linear-gradient(to top, var(--_fade-color), transparent);\n }\n}\n\n.content {\n display: flex;\n gap: var(--marquee-gap, var(--mantine-spacing-md));\n animation-duration: var(--marquee-duration, 100000ms);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n\n .root[data-orientation='horizontal'] > & {\n flex-direction: row;\n animation-name: marquee-horizontal;\n }\n\n .root[data-orientation='vertical'] > & {\n flex-direction: column;\n animation-name: marquee-vertical;\n }\n\n .root[data-reverse] > & {\n animation-direction: reverse;\n }\n\n .root[data-pause-on-hover]:hover > & {\n animation-play-state: paused;\n }\n}\n\n.group {\n display: flex;\n flex-shrink: 0;\n gap: var(--marquee-gap, var(--mantine-spacing-md));\n\n .root[data-orientation='horizontal'] & {\n flex-direction: row;\n }\n\n .root[data-orientation='vertical'] & {\n flex-direction: column;\n }\n}\n"],"mappings":""}
|
|
@@ -8,6 +8,8 @@ import { useStyles } from "../../core/styles-api/use-styles/use-styles.mjs";
|
|
|
8
8
|
import { genericFactory } from "../../core/factory/factory.mjs";
|
|
9
9
|
import { UnstyledButton } from "../UnstyledButton/UnstyledButton.mjs";
|
|
10
10
|
import { InputBase } from "../InputBase/InputBase.mjs";
|
|
11
|
+
import { getCaretPositionAfterPaste } from "./get-caret-position-after-paste/get-caret-position-after-paste.mjs";
|
|
12
|
+
import { normalizePastedValue } from "./normalize-pasted-value/normalize-pasted-value.mjs";
|
|
11
13
|
import { NumberInputChevron } from "./NumberInputChevron.mjs";
|
|
12
14
|
import NumberInput_module_default from "./NumberInput.module.mjs";
|
|
13
15
|
import { useRef } from "react";
|
|
@@ -80,16 +82,18 @@ const defaultProps = {
|
|
|
80
82
|
allowedDecimalSeparators: [".", ","]
|
|
81
83
|
};
|
|
82
84
|
const varsResolver = createVarsResolver((_, { size }) => ({ controls: { "--ni-chevron-size": getSize(size, "ni-chevron-size") } }));
|
|
83
|
-
function
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
|
|
85
|
+
function withTrailingSeparator(value, hasTrailingDecimalSeparator) {
|
|
86
|
+
return hasTrailingDecimalSeparator ? `${value}.` : value;
|
|
87
|
+
}
|
|
88
|
+
function sanitizeInputOnBlur(value, options) {
|
|
89
|
+
const hasTrailingDecimalSeparator = trailingDecimalSeparatorPattern.test(value);
|
|
90
|
+
const trimmed = options.trim ? value.replace(/^0+(?=\d)/, "") : value;
|
|
91
|
+
const parsedValue = parseFloat(trimmed);
|
|
92
|
+
if (Number.isNaN(parsedValue)) return trimmed;
|
|
93
|
+
if (!options.clamp) return options.trim ? withTrailingSeparator(parsedValue, hasTrailingDecimalSeparator) : value;
|
|
94
|
+
const clamped = parsedValue > Number.MAX_SAFE_INTEGER && options.max !== void 0 ? options.max : clamp(parsedValue, options.min, options.max);
|
|
95
|
+
if (!options.trim && clamped === parsedValue) return value;
|
|
96
|
+
return withTrailingSeparator(clamped, hasTrailingDecimalSeparator);
|
|
93
97
|
}
|
|
94
98
|
function clampAndSanitizeBigIntInput(sanitizedValue, options) {
|
|
95
99
|
if (sanitizedValue === "" || sanitizedValue === "-") return sanitizedValue;
|
|
@@ -268,13 +272,15 @@ const NumberInput = genericFactory((_props) => {
|
|
|
268
272
|
const handlePaste = (event) => {
|
|
269
273
|
const pastedText = event.clipboardData.getData("text");
|
|
270
274
|
const _decimalSeparator = others.decimalSeparator || ".";
|
|
271
|
-
const
|
|
272
|
-
|
|
275
|
+
const _thousandSeparator = others.thousandSeparator === true ? "," : others.thousandSeparator === false ? void 0 : others.thousandSeparator;
|
|
276
|
+
const modifiedText = normalizePastedValue(pastedText, {
|
|
277
|
+
decimalSeparator: _decimalSeparator,
|
|
278
|
+
thousandSeparator: _thousandSeparator,
|
|
279
|
+
allowedDecimalSeparators: allowedDecimalSeparators || [".", ","],
|
|
280
|
+
thousandsGroupStyle: others.thousandsGroupStyle
|
|
281
|
+
});
|
|
282
|
+
if (modifiedText !== pastedText) {
|
|
273
283
|
event.preventDefault();
|
|
274
|
-
let modifiedText = pastedText;
|
|
275
|
-
separatorsToReplace.forEach((s) => {
|
|
276
|
-
modifiedText = modifiedText.split(s).join(_decimalSeparator);
|
|
277
|
-
});
|
|
278
284
|
const input = inputRef.current;
|
|
279
285
|
if (input) {
|
|
280
286
|
const start = input.selectionStart ?? 0;
|
|
@@ -283,8 +289,8 @@ const NumberInput = genericFactory((_props) => {
|
|
|
283
289
|
const newValue = currentValue.substring(0, start) + modifiedText + currentValue.substring(end);
|
|
284
290
|
(Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set)?.call(input, newValue);
|
|
285
291
|
input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
286
|
-
const
|
|
287
|
-
setTimeout(() => adjustCursor(
|
|
292
|
+
const rawCaret = start + modifiedText.length;
|
|
293
|
+
setTimeout(() => adjustCursor(getCaretPositionAfterPaste(newValue, rawCaret, input.value, _decimalSeparator)), 0);
|
|
288
294
|
}
|
|
289
295
|
}
|
|
290
296
|
others.onPaste?.(event);
|
|
@@ -324,10 +330,14 @@ const NumberInput = genericFactory((_props) => {
|
|
|
324
330
|
max: maxBigInt,
|
|
325
331
|
clampBehavior
|
|
326
332
|
});
|
|
327
|
-
} else {
|
|
328
|
-
if (clampBehavior === "blur"
|
|
329
|
-
|
|
330
|
-
|
|
333
|
+
} else if (typeof sanitizedValue === "number") {
|
|
334
|
+
if (clampBehavior === "blur") sanitizedValue = clamp(sanitizedValue, minNumber, maxNumber);
|
|
335
|
+
} else if (typeof sanitizedValue === "string") sanitizedValue = sanitizeInputOnBlur(sanitizedValue, {
|
|
336
|
+
min: minNumber,
|
|
337
|
+
max: maxNumber,
|
|
338
|
+
trim: !!trimLeadingZeroesOnBlur && getDecimalPlaces(sanitizedValue) < 15,
|
|
339
|
+
clamp: clampBehavior === "blur"
|
|
340
|
+
});
|
|
331
341
|
if (_value !== sanitizedValue) setValue(sanitizedValue);
|
|
332
342
|
onBlur?.(event);
|
|
333
343
|
};
|