@lmb-it/kitsconcerto-native 0.1.284 → 0.1.286

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.
Files changed (75) hide show
  1. package/apps/mobile/src/Core/AutoComplete/index.cjs +12 -4
  2. package/apps/mobile/src/Core/AutoComplete/index.cjs.map +1 -1
  3. package/apps/mobile/src/Core/AutoComplete/index.js +12 -4
  4. package/apps/mobile/src/Core/AutoComplete/index.js.map +1 -1
  5. package/apps/mobile/src/Core/MultiSelect/index.cjs +7 -4
  6. package/apps/mobile/src/Core/MultiSelect/index.cjs.map +1 -1
  7. package/apps/mobile/src/Core/MultiSelect/index.js +7 -4
  8. package/apps/mobile/src/Core/MultiSelect/index.js.map +1 -1
  9. package/apps/mobile/src/ui/accordion/index.js +2 -2
  10. package/components/ImageCropper/compression.cjs +63 -0
  11. package/components/ImageCropper/compression.cjs.map +1 -0
  12. package/components/ImageCropper/compression.js +58 -0
  13. package/components/ImageCropper/compression.js.map +1 -0
  14. package/components/ImageCropper/constants.cjs +35 -0
  15. package/components/ImageCropper/constants.cjs.map +1 -0
  16. package/components/ImageCropper/constants.js +23 -0
  17. package/components/ImageCropper/constants.js.map +1 -0
  18. package/components/ImageCropper/cropperState.cjs +119 -0
  19. package/components/ImageCropper/cropperState.cjs.map +1 -0
  20. package/components/ImageCropper/cropperState.js +114 -0
  21. package/components/ImageCropper/cropperState.js.map +1 -0
  22. package/components/ImageCropper/encode.cjs +45 -0
  23. package/components/ImageCropper/encode.cjs.map +1 -0
  24. package/components/ImageCropper/encode.js +42 -0
  25. package/components/ImageCropper/encode.js.map +1 -0
  26. package/components/ImageCropper/encoderRegistry.cjs +13 -0
  27. package/components/ImageCropper/encoderRegistry.cjs.map +1 -0
  28. package/components/ImageCropper/encoderRegistry.js +9 -0
  29. package/components/ImageCropper/encoderRegistry.js.map +1 -0
  30. package/components/ImageCropper/encoders/rnImageEncoder.cjs +54 -0
  31. package/components/ImageCropper/encoders/rnImageEncoder.cjs.map +1 -0
  32. package/components/ImageCropper/encoders/rnImageEncoder.js +51 -0
  33. package/components/ImageCropper/encoders/rnImageEncoder.js.map +1 -0
  34. package/components/ImageCropper/geometry.cjs +208 -0
  35. package/components/ImageCropper/geometry.cjs.map +1 -0
  36. package/components/ImageCropper/geometry.js +186 -0
  37. package/components/ImageCropper/geometry.js.map +1 -0
  38. package/components/ImageCropper/index.cjs +436 -0
  39. package/components/ImageCropper/index.cjs.map +1 -0
  40. package/components/ImageCropper/index.js +434 -0
  41. package/components/ImageCropper/index.js.map +1 -0
  42. package/components/ImageCropper/pinchZoom.cjs +8 -0
  43. package/components/ImageCropper/pinchZoom.cjs.map +1 -0
  44. package/components/ImageCropper/pinchZoom.js +5 -0
  45. package/components/ImageCropper/pinchZoom.js.map +1 -0
  46. package/components/ImageCropper/useImageSource.cjs +87 -0
  47. package/components/ImageCropper/useImageSource.cjs.map +1 -0
  48. package/components/ImageCropper/useImageSource.js +84 -0
  49. package/components/ImageCropper/useImageSource.js.map +1 -0
  50. package/form/helpers/FormContainer/index.cjs +12 -2
  51. package/form/helpers/FormContainer/index.cjs.map +1 -1
  52. package/form/helpers/FormContainer/index.js +12 -2
  53. package/form/helpers/FormContainer/index.js.map +1 -1
  54. package/form/selects/AutoComplete/index.cjs +10 -1
  55. package/form/selects/AutoComplete/index.cjs.map +1 -1
  56. package/form/selects/AutoComplete/index.js +11 -2
  57. package/form/selects/AutoComplete/index.js.map +1 -1
  58. package/form/selects/MultiSelect/index.cjs +8 -1
  59. package/form/selects/MultiSelect/index.cjs.map +1 -1
  60. package/form/selects/MultiSelect/index.js +9 -2
  61. package/form/selects/MultiSelect/index.js.map +1 -1
  62. package/hooks/useComponentDefaults.cjs +62 -8
  63. package/hooks/useComponentDefaults.cjs.map +1 -1
  64. package/hooks/useComponentDefaults.js +62 -8
  65. package/hooks/useComponentDefaults.js.map +1 -1
  66. package/index.cjs +120 -115
  67. package/index.cjs.map +1 -1
  68. package/index.d.ts +494 -16
  69. package/index.js +2 -0
  70. package/index.js.map +1 -1
  71. package/package.json +13 -1
  72. package/packages/types/src/Theme/defaultTheme.cjs +135 -4
  73. package/packages/types/src/Theme/defaultTheme.cjs.map +1 -1
  74. package/packages/types/src/Theme/defaultTheme.js +135 -4
  75. package/packages/types/src/Theme/defaultTheme.js.map +1 -1
@@ -0,0 +1,87 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactNative = require('react-native');
5
+
6
+ const resolveNativeSource = (source) => {
7
+ if (!source) return { kind: "none" };
8
+ if (typeof source === "number") {
9
+ const resolved = reactNative.Image.resolveAssetSource(source);
10
+ if (!resolved?.uri || !resolved.width || !resolved.height) {
11
+ return {
12
+ kind: "error",
13
+ error: { reason: "decode-failed", message: "That bundled image could not be resolved." }
14
+ };
15
+ }
16
+ return {
17
+ kind: "ready",
18
+ image: { uri: resolved.uri, width: resolved.width, height: resolved.height }
19
+ };
20
+ }
21
+ if (typeof source !== "string") {
22
+ return {
23
+ kind: "error",
24
+ error: {
25
+ reason: "decode-failed",
26
+ message: "On a device the cropper needs a file URI or a require()'d asset, not a File object."
27
+ }
28
+ };
29
+ }
30
+ return { kind: "measure", uri: source };
31
+ };
32
+ const useImageSource = (source, onError) => {
33
+ const [image, setImage] = React.useState(null);
34
+ const [error, setError] = React.useState(null);
35
+ const [loading, setLoading] = React.useState(false);
36
+ React.useEffect(() => {
37
+ setImage(null);
38
+ setError(null);
39
+ const plan = resolveNativeSource(source);
40
+ if (plan.kind === "none") {
41
+ setLoading(false);
42
+ return;
43
+ }
44
+ if (plan.kind === "error") {
45
+ setError(plan.error);
46
+ setLoading(false);
47
+ onError?.(plan.error);
48
+ return;
49
+ }
50
+ if (plan.kind === "ready") {
51
+ setImage(plan.image);
52
+ setLoading(false);
53
+ return;
54
+ }
55
+ setLoading(true);
56
+ let cancelled = false;
57
+ reactNative.Image.getSize(
58
+ plan.uri,
59
+ (width, height) => {
60
+ if (cancelled) return;
61
+ setImage({ uri: plan.uri, width, height });
62
+ setLoading(false);
63
+ },
64
+ () => {
65
+ if (cancelled) return;
66
+ const failure = {
67
+ // ⚠️ THE MESSAGE NAMES THE LIKELY CAUSE, because the
68
+ // honest-sounding one sent us looking at the image. The file
69
+ // is usually fine; what failed is REACHING it.
70
+ reason: "decode-failed",
71
+ message: "That image could not be read. If it is a bundled asset, pass require('\u2026') instead of a URI \u2014 a dev-server URL is often unreachable from a physical device."
72
+ };
73
+ setError(failure);
74
+ setLoading(false);
75
+ onError?.(failure);
76
+ }
77
+ );
78
+ return () => {
79
+ cancelled = true;
80
+ };
81
+ }, [source]);
82
+ return { image, loading, error };
83
+ };
84
+
85
+ exports.resolveNativeSource = resolveNativeSource;
86
+ exports.useImageSource = useImageSource;
87
+ //# sourceMappingURL=useImageSource.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageSource.cjs","sources":["../../../../src/components/ImageCropper/useImageSource.native.ts"],"sourcesContent":["import {useEffect, useState} from \"react\";\nimport {Image} from \"react-native\";\nimport type {ICropError} from \"@lmb-it/kitsconcerto-types\";\n\n/** What the stage needs before it can draw anything. */\nexport interface ILoadedImage {\n uri: string;\n width: number;\n height: number;\n}\n\n/**\n * Resolves a URI to its natural pixel size.\n *\n * ⛔ THE SIZE IS FETCHED, NOT GUESSED, AND NOTHING CAN DRAW UNTIL IT ARRIVES.\n * Every number in `geometry.ts` is relative to the source's real dimensions; a\n * stage that renders against a placeholder and corrects later shows the user a\n * framing that then jumps. `Image.getSize` is asynchronous for a remote URI and\n * near-instant for a local one, so the wait is only visible on the former.\n *\n * ⛔ A BUNDLED ASSET NEVER TOUCHES THE NETWORK, AND THAT IS THE WHOLE POINT OF\n * THE `require()` BRANCH. `Image.resolveAssetSource` returns `{uri, width,\n * height, scale}` SYNCHRONOUSLY from the asset registry — the dimensions are\n * already known, so there is nothing to fetch and nothing to fail.\n *\n * ⚠️ THIS WAS A REAL BUG, ON A REAL PHONE. The native stories resolved the\n * asset and then threw the dimensions away, passing only `.uri` — so this hook\n * took the string branch and asked `Image.getSize` to fetch them back. In\n * development that URI points at the Metro dev server; a physical device on a\n * different host cannot reach it, `getSize` failed, and the cropper reported\n * \"That image could not be opened\" over a perfectly good PNG. In a release\n * build the same URI is not fetchable that way either. The UI rendered, the\n * image never did.\n *\n * ⚠️ NATIVE TAKES A URI OR AN ASSET, NOT A `File`. The prop accepts\n * `string | File | number` so one config compiles on both platforms — the same\n * accepted-and-inert contract the selects' `popup` carries — but there is no\n * `File` on a device, and a picker hands back a `file://` path. A `File` here\n * is reported rather than ignored, because silently showing nothing is worse.\n */\n/**\n * What to do with a given `source`, decided without React.\n *\n * ⛔ A PURE FUNCTION BECAUSE THIS REPO'S VITEST HAS NO DOM — the same reason\n * `cropperState` is a reducer rather than a hook. The branch below is the one\n * that shipped a bug to a physical phone; leaving it inside an effect would\n * have meant shipping the fix untested too, since React's ESM exports cannot\n * be spied on.\n */\nexport type NativeSourcePlan =\n /** Nothing to load. */\n | {kind: \"none\"}\n /** A bundled asset: dimensions came back with it, no I/O needed. */\n | {kind: \"ready\"; image: ILoadedImage}\n /** A URI of unknown size: `Image.getSize` has to go and look. */\n | {kind: \"measure\"; uri: string}\n | {kind: \"error\"; error: ICropError};\n\nexport const resolveNativeSource = (\n source: string | File | number | null | undefined,\n): NativeSourcePlan => {\n if (!source) return {kind: \"none\"};\n\n /* ⛔ A BUNDLED ASSET NEVER TOUCHES THE NETWORK. `resolveAssetSource`\n returns `{uri, width, height, scale}` synchronously from the asset\n registry — the dimensions are already known, so there is nothing to\n fetch and nothing to fail. */\n if (typeof source === \"number\") {\n const resolved = Image.resolveAssetSource(source);\n if (!resolved?.uri || !resolved.width || !resolved.height) {\n // ⚠️ TYPED NON-NULL, NOT ALWAYS NON-NULL. An asset the packager did\n // not register comes back null or dimensionless, and reading `.uri`\n // off that throws inside an effect — which React surfaces as a\n // render crash somewhere else, not as this component's own error.\n return {\n kind: \"error\",\n error: {reason: \"decode-failed\", message: \"That bundled image could not be resolved.\"},\n };\n }\n return {\n kind: \"ready\",\n image: {uri: resolved.uri, width: resolved.width, height: resolved.height},\n };\n }\n\n if (typeof source !== \"string\") {\n return {\n kind: \"error\",\n error: {\n reason: \"decode-failed\",\n message: \"On a device the cropper needs a file URI or a require()'d asset, not a File object.\",\n },\n };\n }\n\n return {kind: \"measure\", uri: source};\n};\n\nexport const useImageSource = (\n source: string | File | number | null | undefined,\n onError?: (error: ICropError) => void,\n): {image: ILoadedImage | null; loading: boolean; error: ICropError | null} => {\n const [image, setImage] = useState<ILoadedImage | null>(null);\n const [error, setError] = useState<ICropError | null>(null);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n setImage(null);\n setError(null);\n\n const plan = resolveNativeSource(source);\n\n if (plan.kind === \"none\") {\n setLoading(false);\n return;\n }\n\n if (plan.kind === \"error\") {\n setError(plan.error);\n setLoading(false);\n onError?.(plan.error);\n return;\n }\n\n if (plan.kind === \"ready\") {\n setImage(plan.image);\n setLoading(false);\n return;\n }\n\n setLoading(true);\n let cancelled = false;\n\n Image.getSize(\n plan.uri,\n (width, height) => {\n if (cancelled) return;\n setImage({uri: plan.uri, width, height});\n setLoading(false);\n },\n () => {\n if (cancelled) return;\n const failure: ICropError = {\n // ⚠️ THE MESSAGE NAMES THE LIKELY CAUSE, because the\n // honest-sounding one sent us looking at the image. The file\n // is usually fine; what failed is REACHING it.\n reason: \"decode-failed\",\n message:\n \"That image could not be read. If it is a bundled asset, pass \" +\n \"require('…') instead of a URI — a dev-server URL is often \" +\n \"unreachable from a physical device.\",\n };\n setError(failure);\n setLoading(false);\n onError?.(failure);\n },\n );\n\n return () => {\n cancelled = true;\n };\n // ⚠️ `onError` IS DELIBERATELY NOT A DEPENDENCY — consumers pass an inline\n // arrow far more often than not, and including it re-runs the load on\n // every parent render. Same reasoning as the web twin.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [source]);\n\n return {image, loading, error};\n};\n"],"names":["Image","useState","useEffect"],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { Image } from 'react-native';
3
+
4
+ const resolveNativeSource = (source) => {
5
+ if (!source) return { kind: "none" };
6
+ if (typeof source === "number") {
7
+ const resolved = Image.resolveAssetSource(source);
8
+ if (!resolved?.uri || !resolved.width || !resolved.height) {
9
+ return {
10
+ kind: "error",
11
+ error: { reason: "decode-failed", message: "That bundled image could not be resolved." }
12
+ };
13
+ }
14
+ return {
15
+ kind: "ready",
16
+ image: { uri: resolved.uri, width: resolved.width, height: resolved.height }
17
+ };
18
+ }
19
+ if (typeof source !== "string") {
20
+ return {
21
+ kind: "error",
22
+ error: {
23
+ reason: "decode-failed",
24
+ message: "On a device the cropper needs a file URI or a require()'d asset, not a File object."
25
+ }
26
+ };
27
+ }
28
+ return { kind: "measure", uri: source };
29
+ };
30
+ const useImageSource = (source, onError) => {
31
+ const [image, setImage] = useState(null);
32
+ const [error, setError] = useState(null);
33
+ const [loading, setLoading] = useState(false);
34
+ useEffect(() => {
35
+ setImage(null);
36
+ setError(null);
37
+ const plan = resolveNativeSource(source);
38
+ if (plan.kind === "none") {
39
+ setLoading(false);
40
+ return;
41
+ }
42
+ if (plan.kind === "error") {
43
+ setError(plan.error);
44
+ setLoading(false);
45
+ onError?.(plan.error);
46
+ return;
47
+ }
48
+ if (plan.kind === "ready") {
49
+ setImage(plan.image);
50
+ setLoading(false);
51
+ return;
52
+ }
53
+ setLoading(true);
54
+ let cancelled = false;
55
+ Image.getSize(
56
+ plan.uri,
57
+ (width, height) => {
58
+ if (cancelled) return;
59
+ setImage({ uri: plan.uri, width, height });
60
+ setLoading(false);
61
+ },
62
+ () => {
63
+ if (cancelled) return;
64
+ const failure = {
65
+ // ⚠️ THE MESSAGE NAMES THE LIKELY CAUSE, because the
66
+ // honest-sounding one sent us looking at the image. The file
67
+ // is usually fine; what failed is REACHING it.
68
+ reason: "decode-failed",
69
+ message: "That image could not be read. If it is a bundled asset, pass require('\u2026') instead of a URI \u2014 a dev-server URL is often unreachable from a physical device."
70
+ };
71
+ setError(failure);
72
+ setLoading(false);
73
+ onError?.(failure);
74
+ }
75
+ );
76
+ return () => {
77
+ cancelled = true;
78
+ };
79
+ }, [source]);
80
+ return { image, loading, error };
81
+ };
82
+
83
+ export { resolveNativeSource, useImageSource };
84
+ //# sourceMappingURL=useImageSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageSource.js","sources":["../../../../src/components/ImageCropper/useImageSource.native.ts"],"sourcesContent":["import {useEffect, useState} from \"react\";\nimport {Image} from \"react-native\";\nimport type {ICropError} from \"@lmb-it/kitsconcerto-types\";\n\n/** What the stage needs before it can draw anything. */\nexport interface ILoadedImage {\n uri: string;\n width: number;\n height: number;\n}\n\n/**\n * Resolves a URI to its natural pixel size.\n *\n * ⛔ THE SIZE IS FETCHED, NOT GUESSED, AND NOTHING CAN DRAW UNTIL IT ARRIVES.\n * Every number in `geometry.ts` is relative to the source's real dimensions; a\n * stage that renders against a placeholder and corrects later shows the user a\n * framing that then jumps. `Image.getSize` is asynchronous for a remote URI and\n * near-instant for a local one, so the wait is only visible on the former.\n *\n * ⛔ A BUNDLED ASSET NEVER TOUCHES THE NETWORK, AND THAT IS THE WHOLE POINT OF\n * THE `require()` BRANCH. `Image.resolveAssetSource` returns `{uri, width,\n * height, scale}` SYNCHRONOUSLY from the asset registry — the dimensions are\n * already known, so there is nothing to fetch and nothing to fail.\n *\n * ⚠️ THIS WAS A REAL BUG, ON A REAL PHONE. The native stories resolved the\n * asset and then threw the dimensions away, passing only `.uri` — so this hook\n * took the string branch and asked `Image.getSize` to fetch them back. In\n * development that URI points at the Metro dev server; a physical device on a\n * different host cannot reach it, `getSize` failed, and the cropper reported\n * \"That image could not be opened\" over a perfectly good PNG. In a release\n * build the same URI is not fetchable that way either. The UI rendered, the\n * image never did.\n *\n * ⚠️ NATIVE TAKES A URI OR AN ASSET, NOT A `File`. The prop accepts\n * `string | File | number` so one config compiles on both platforms — the same\n * accepted-and-inert contract the selects' `popup` carries — but there is no\n * `File` on a device, and a picker hands back a `file://` path. A `File` here\n * is reported rather than ignored, because silently showing nothing is worse.\n */\n/**\n * What to do with a given `source`, decided without React.\n *\n * ⛔ A PURE FUNCTION BECAUSE THIS REPO'S VITEST HAS NO DOM — the same reason\n * `cropperState` is a reducer rather than a hook. The branch below is the one\n * that shipped a bug to a physical phone; leaving it inside an effect would\n * have meant shipping the fix untested too, since React's ESM exports cannot\n * be spied on.\n */\nexport type NativeSourcePlan =\n /** Nothing to load. */\n | {kind: \"none\"}\n /** A bundled asset: dimensions came back with it, no I/O needed. */\n | {kind: \"ready\"; image: ILoadedImage}\n /** A URI of unknown size: `Image.getSize` has to go and look. */\n | {kind: \"measure\"; uri: string}\n | {kind: \"error\"; error: ICropError};\n\nexport const resolveNativeSource = (\n source: string | File | number | null | undefined,\n): NativeSourcePlan => {\n if (!source) return {kind: \"none\"};\n\n /* ⛔ A BUNDLED ASSET NEVER TOUCHES THE NETWORK. `resolveAssetSource`\n returns `{uri, width, height, scale}` synchronously from the asset\n registry — the dimensions are already known, so there is nothing to\n fetch and nothing to fail. */\n if (typeof source === \"number\") {\n const resolved = Image.resolveAssetSource(source);\n if (!resolved?.uri || !resolved.width || !resolved.height) {\n // ⚠️ TYPED NON-NULL, NOT ALWAYS NON-NULL. An asset the packager did\n // not register comes back null or dimensionless, and reading `.uri`\n // off that throws inside an effect — which React surfaces as a\n // render crash somewhere else, not as this component's own error.\n return {\n kind: \"error\",\n error: {reason: \"decode-failed\", message: \"That bundled image could not be resolved.\"},\n };\n }\n return {\n kind: \"ready\",\n image: {uri: resolved.uri, width: resolved.width, height: resolved.height},\n };\n }\n\n if (typeof source !== \"string\") {\n return {\n kind: \"error\",\n error: {\n reason: \"decode-failed\",\n message: \"On a device the cropper needs a file URI or a require()'d asset, not a File object.\",\n },\n };\n }\n\n return {kind: \"measure\", uri: source};\n};\n\nexport const useImageSource = (\n source: string | File | number | null | undefined,\n onError?: (error: ICropError) => void,\n): {image: ILoadedImage | null; loading: boolean; error: ICropError | null} => {\n const [image, setImage] = useState<ILoadedImage | null>(null);\n const [error, setError] = useState<ICropError | null>(null);\n const [loading, setLoading] = useState(false);\n\n useEffect(() => {\n setImage(null);\n setError(null);\n\n const plan = resolveNativeSource(source);\n\n if (plan.kind === \"none\") {\n setLoading(false);\n return;\n }\n\n if (plan.kind === \"error\") {\n setError(plan.error);\n setLoading(false);\n onError?.(plan.error);\n return;\n }\n\n if (plan.kind === \"ready\") {\n setImage(plan.image);\n setLoading(false);\n return;\n }\n\n setLoading(true);\n let cancelled = false;\n\n Image.getSize(\n plan.uri,\n (width, height) => {\n if (cancelled) return;\n setImage({uri: plan.uri, width, height});\n setLoading(false);\n },\n () => {\n if (cancelled) return;\n const failure: ICropError = {\n // ⚠️ THE MESSAGE NAMES THE LIKELY CAUSE, because the\n // honest-sounding one sent us looking at the image. The file\n // is usually fine; what failed is REACHING it.\n reason: \"decode-failed\",\n message:\n \"That image could not be read. If it is a bundled asset, pass \" +\n \"require('…') instead of a URI — a dev-server URL is often \" +\n \"unreachable from a physical device.\",\n };\n setError(failure);\n setLoading(false);\n onError?.(failure);\n },\n );\n\n return () => {\n cancelled = true;\n };\n // ⚠️ `onError` IS DELIBERATELY NOT A DEPENDENCY — consumers pass an inline\n // arrow far more often than not, and including it re-runs the load on\n // every parent render. Same reasoning as the web twin.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [source]);\n\n return {image, loading, error};\n};\n"],"names":[],"mappings":"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"}
@@ -112,9 +112,18 @@ const KitsContainer = (props) => {
112
112
  containerStyle,
113
113
  disabled,
114
114
  bare,
115
- elementStyles: parentElementStyles
115
+ elementStyles: parentElementStyles,
116
+ elementProps: parentElementProps
116
117
  } = props;
117
118
  const elStyles = useResolvedElementStyles.default(parentElementStyles || {});
119
+ const elProps = parentElementProps || {};
120
+ const stripClassName = (slot) => {
121
+ if (!slot) return {};
122
+ const { className: _ignoredOnNative, ...rest } = slot;
123
+ return rest;
124
+ };
125
+ const containerSlotProps = stripClassName(elProps.container);
126
+ const inputGroupSlotProps = stripClassName(elProps.inputGroup);
118
127
  const { resolveToken } = KitsThemeProvider_native.useKitsTheme();
119
128
  const themedFont = useThemedFont.default("body");
120
129
  const elementId = id ? `${id}_element` : _.uniqueId("element_");
@@ -168,7 +177,7 @@ const KitsContainer = (props) => {
168
177
  paddingVertical: 8,
169
178
  backgroundColor: resolveToken("bg-input")
170
179
  };
171
- const contentElement = /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: inputGroupStyle, children: [
180
+ const contentElement = /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: inputGroupStyle, ...inputGroupSlotProps, children: [
172
181
  leftAddon ? /* @__PURE__ */ jsxRuntime.jsx(
173
182
  reactNative.View,
174
183
  {
@@ -207,6 +216,7 @@ const KitsContainer = (props) => {
207
216
  isDisabled: disabled,
208
217
  isReadOnly: disabled,
209
218
  isRequired: required,
219
+ ...containerSlotProps,
210
220
  style: {
211
221
  width: "100%",
212
222
  gap: 4,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../../src/form/helpers/FormContainer/index.native.tsx"],"sourcesContent":["import React, { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { uniqueId } from \"lodash\";\nimport ErrorMessage from \"../ErrorMessage\";\nimport type {IKitsContainer} from \"@lmb-it/kitsconcerto-types\";\nimport {\n FormControl,\n FormControlHelper,\n FormControlHelperText,\n style as resolveStyle,\n} from \"@lmb-it/kitsconcertomobile\"\nimport { Label, Text, useKitsTheme } from \"../../../_compat\";\nimport {useResolvedElementStyles, useThemedFont} from \"@lmb-it/kitsconcerto/hooks\";\n\n/**\n * KitsContainer (native) — wraps all form inputs with label, addons, helper\n * text, and errors. Mirror of the web variant: a pure renderer that does NO\n * independent theme lookup. Every slot style comes from `elementStyles`\n * passed by the parent input (already merged through the\n * FormElement < Input/Select < InputText/DropdownSelect/… < per-instance slots\n * chain by the parent's `useComponentDefaults` call).\n *\n * Addon rendering is inlined here (matches web FormContainer). There is NO\n * `Addons` component on either platform anymore — the previous native Addons\n * helper re-resolved tokens and hardcoded `borderRadius / borderWidth /\n * padding / backgroundColor / borderColor` defaults that clobbered\n * `kitsTheme.components.*.leftAddon.style` overrides. Both bugs are fixed by\n * deleting the indirection.\n *\n * Element slots applied here (identical contract to web):\n * container → outer FormControl wrapper\n * label → Label component (plain Text path on native — see Label.native)\n * inputGroup → input group wrapper (around addons + input). On native this\n * wrapper carries the visual border that web gets from the\n * `.p-inputgroup` CSS class.\n * leftAddon → left addon View\n * rightAddon → right addon View\n * helperText → helper text below the group\n * error → error message below the group\n *\n * The `root` slot is NOT applied here — it is applied by the parent form\n * input component directly to the inner Input/Textarea element.\n */\nconst KitsContainer: FC<PropsWithChildren<IKitsContainer>> = (props) => {\n const {\n id,\n helperText,\n children,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n required,\n hideError,\n label,\n isFloatedLabel,\n containerStyle,\n disabled,\n bare,\n elementStyles: parentElementStyles,\n } = props;\n\n // Pure renderer: resolve the elementStyles passed in by the parent.\n // No `useComponentDefaults('FormContainer', …)` lookup — that key is\n // intentionally not part of the consumer-facing theme contract.\n const elStyles = useResolvedElementStyles(parentElementStyles || {});\n const { resolveToken } = useKitsTheme();\n const themedFont = useThemedFont('body');\n\n // Generate a unique element ID (for parity with web; not used in native labels)\n const elementId = id ? `${id}_element` : uniqueId(\"element_\");\n\n // Derive label placement from the label prop\n const placement = useMemo(() => {\n if (label && typeof label === 'object' && 'placement' in label) {\n return label.placement; // \"RL\" | \"B\" | \"T\"\n }\n return \"T\"; // default: top\n }, [label]);\n\n // Determine layout direction based on placement\n // T = top (column, label first), B = bottom (column-reverse), RL = side-by-side (row)\n const isHorizontal = placement === \"RL\";\n const isBottom = placement === \"B\";\n\n // Label uses the plain Text path (NOT the FormControlLabel path) because\n // @lmb-it/kitsconcertomobile's FormControlLabelText strips arbitrary\n // inline styles, which broke `kitsTheme.components.Input.label.style`\n // overrides on native. The plain Text path forwards `style` directly.\n const labelElement = !isFloatedLabel ? (\n <Label label={label} elementId={elementId} required={required} style={elStyles.label || undefined} />\n ) : null;\n\n /**\n * Inline addon renderer. Mirrors the dispatch web uses in FormContainer\n * (string → text, ReactElement → element) AND adds the function-arg\n * branch native needs because lucide-react-native icons are passed as\n * functions `(props) => <Icon …/>`. The function-arg branch never runs\n * on web (web never goes through this code) so it cannot affect web.\n */\n const renderAddon = (\n addon: IKitsContainer[\"leftAddon\"] | IKitsContainer[\"rightAddon\"],\n ) => {\n if (!addon) return null;\n if (typeof addon === \"string\" || typeof addon === \"number\") {\n return <Text fontSize={14}>{addon}</Text>;\n }\n if (typeof addon === \"function\") {\n return (addon as (args: { size: number }) => React.ReactNode)({ size: 16 });\n }\n if (React.isValidElement(addon)) {\n return addon;\n }\n return null;\n };\n\n // Resolved inputGroup wrapper style. The default theme provides\n // `Input.inputGroup.style.{borderColor, borderRadius, borderWidth, height}`\n // — these are what give the group its visual frame. Defaults are layered\n // *under* the user's resolved style, so a per-instance override always wins.\n //\n // The `invalid` border color is applied as a fallback default (after\n // theme defaults, before user `inputGroup.borderColor` override). When\n // `bare` is set, the whole frame is suppressed (matches web's\n // `bareInputGroupStyle`).\n const inputGroupStyle = useMemo(() => {\n if (bare) {\n // Bare mode (FilePicker, Radio, Checkbox group, …): drop ALL\n // inputGroup chrome including `height: 52` from the theme. Web's\n // FormContainer does the same — it passes `style={{}}` when\n // bare (see helpers/FormContainer/index.web.tsx, the bare\n // branch of the row Flex). Without this, the non-classic file\n // uploader's 200px dashed drop zone was being squashed to 52px.\n return {\n width: \"100%\" as const,\n borderWidth: 0,\n borderRadius: 0,\n overflow: \"visible\" as const,\n };\n }\n const userStyle = elStyles.inputGroup || {};\n const userOverrodeBorderColor = \"borderColor\" in userStyle;\n return {\n width: \"100%\" as const,\n flexDirection: \"row\" as const,\n alignItems: \"stretch\" as const,\n overflow: \"hidden\" as const,\n ...userStyle,\n ...(invalid && !userOverrodeBorderColor\n ? { borderColor: resolveToken(\"danger\") }\n : {}),\n };\n }, [bare, elStyles.inputGroup, invalid, resolveToken]);\n\n // Addon baseline chrome — mirrors what PrimeReact's `.p-inputgroup-addon`\n // CSS class gives web addons (gray fill + horizontal padding + 1px\n // separator border on the input-facing edge). On web these defaults\n // come from CSS; on native we must apply them inline. Theme overrides\n // (`elStyles.leftAddon` / `rightAddon`) are spread LAST so per-instance\n // values always win. The separator border colour falls back to the\n // inputGroup border colour for visual continuity.\n const addonSeparatorColor = (\n (elStyles.inputGroup && elStyles.inputGroup.borderColor) ||\n resolveToken(\"border\")\n );\n const addonBaseStyle = {\n alignItems: \"center\" as const,\n justifyContent: \"center\" as const,\n paddingHorizontal: 12,\n paddingVertical: 8,\n backgroundColor: resolveToken(\"bg-input\"),\n };\n\n const contentElement = (\n <View style={inputGroupStyle}>\n {leftAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderEndWidth: 1,\n borderEndColor: addonSeparatorColor,\n ...(elStyles.leftAddon || {}),\n }}\n >\n {renderAddon(leftAddon)}\n </View>\n ) : null}\n\n {/* `justifyContent: 'center'` vertically centres the inner Input\n inside the 52px-tall inputGroup (matching web, where flex\n items default to vertical alignment via the inputGroup row\n + the input's intrinsic line-box centring). Without this,\n placeholders and selected values sat near the top edge of\n the input. Tall children that already fill the height\n (textarea) are unaffected because `justifyContent: 'center'`\n is a no-op on items that match the parent's cross-axis. */}\n <View style={{ flex: 1, justifyContent: 'center' }}>{children}</View>\n\n {rightAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderStartWidth: 1,\n borderStartColor: addonSeparatorColor,\n ...(elStyles.rightAddon || {}),\n }}\n >\n {renderAddon(rightAddon)}\n </View>\n ) : null}\n </View>\n );\n\n const containerRnStyle = useMemo(\n () => (containerStyle && Object.keys(containerStyle).length ? resolveStyle(containerStyle) : {}),\n [containerStyle],\n );\n\n return(\n <FormControl\n isInvalid={invalid}\n size=\"md\"\n isDisabled={disabled}\n isReadOnly={disabled}\n isRequired={required}\n style={{\n width:'100%', gap: 4,\n // `bare` strips the container's DEFAULT frame, but must not\n // override an explicit `container` slot. Spread it FIRST so a\n // user's borderRadius / borderWidth / overflow (e.g. an Object\n // or Group styled as a card) wins over the reset.\n ...(bare ? { borderWidth: 0, borderRadius: 0, overflow: 'visible' } : {}),\n ...(elStyles.container || {}),\n ...(containerRnStyle || {}),\n }}\n >\n {isHorizontal ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: '100%' }}>\n {labelElement}\n <View style={{ flex: 1 }}>{contentElement}</View>\n </View>\n ) : isBottom ? (\n <>\n {contentElement}\n {labelElement}\n </>\n ) : (\n <>\n {labelElement}\n {contentElement}\n </>\n )}\n {helperText && typeof helperText !== \"function\" && <FormControlHelper>\n <FormControlHelperText style={{...(themedFont ? {fontFamily: themedFont} : {}), ...(elStyles.helperText || {})}}>\n {helperText}\n </FormControlHelperText>\n </FormControlHelper>}\n\n {!hideError && <ErrorMessage invalid={invalid} errors={errors} style={elStyles.error || undefined} />}\n </FormControl>\n )\n};\n\nexport default KitsContainer;\n"],"names":["useResolvedElementStyles","useKitsTheme","useThemedFont","uniqueId","useMemo","jsx","Label","Text","jsxs","View","resolveStyle","FormControl","Fragment","FormControlHelper","FormControlHelperText","ErrorMessage"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAM,aAAA,GAAuD,CAAC,KAAA,KAAU;AACpE,EAAA,MAAM;AAAA,IACF,EAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,aAAA,EAAe;AAAA,GACnB,GAAI,KAAA;AAKJ,EAAA,MAAM,QAAA,GAAWA,gCAAA,CAAyB,mBAAA,IAAuB,EAAE,CAAA;AACnE,EAAA,MAAM,EAAE,YAAA,EAAa,GAAIC,qCAAA,EAAa;AACtC,EAAA,MAAM,UAAA,GAAaC,sBAAc,MAAM,CAAA;AAGvC,EAAA,MAAM,YAAY,EAAA,GAAK,CAAA,EAAG,EAAE,CAAA,QAAA,CAAA,GAAaC,WAAS,UAAU,CAAA;AAG5D,EAAA,MAAM,SAAA,GAAYC,cAAQ,MAAM;AAC5B,IAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,eAAe,KAAA,EAAO;AAC5D,MAAA,OAAO,KAAA,CAAM,SAAA;AAAA,IACjB;AACA,IAAA,OAAO,GAAA;AAAA,EACX,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAIV,EAAA,MAAM,eAAe,SAAA,KAAc,IAAA;AACnC,EAAA,MAAM,WAAW,SAAA,KAAc,GAAA;AAM/B,EAAA,MAAM,YAAA,GAAe,CAAC,cAAA,mBAClBC,cAAA,CAACC,oBAAA,EAAA,EAAM,KAAA,EAAc,SAAA,EAAsB,QAAA,EAAoB,KAAA,EAAO,QAAA,CAAS,KAAA,IAAS,MAAA,EAAW,CAAA,GACnG,IAAA;AASJ,EAAA,MAAM,WAAA,GAAc,CAChB,KAAA,KACC;AACD,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,UAAU,QAAA,EAAU;AACxD,MAAA,uBAAOD,cAAA,CAACE,oBAAA,EAAA,EAAK,QAAA,EAAU,EAAA,EAAK,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACtC;AACA,IAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC7B,MAAA,OAAQ,KAAA,CAAsD,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,IAC9E;AACA,IAAA,IAAI,KAAA,CAAM,cAAA,CAAe,KAAK,CAAA,EAAG;AAC7B,MAAA,OAAO,KAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA;AAAA,EACX,CAAA;AAWA,EAAA,MAAM,eAAA,GAAkBH,cAAQ,MAAM;AAClC,IAAA,IAAI,IAAA,EAAM;AAON,MAAA,OAAO;AAAA,QACH,KAAA,EAAO,MAAA;AAAA,QACP,WAAA,EAAa,CAAA;AAAA,QACb,YAAA,EAAc,CAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACd;AAAA,IACJ;AACA,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,IAAc,EAAC;AAC1C,IAAA,MAAM,0BAA0B,aAAA,IAAiB,SAAA;AACjD,IAAA,OAAO;AAAA,MACH,KAAA,EAAO,MAAA;AAAA,MACP,aAAA,EAAe,KAAA;AAAA,MACf,UAAA,EAAY,SAAA;AAAA,MACZ,QAAA,EAAU,QAAA;AAAA,MACV,GAAG,SAAA;AAAA,MACH,GAAI,OAAA,IAAW,CAAC,uBAAA,GACV,EAAE,aAAa,YAAA,CAAa,QAAQ,CAAA,EAAE,GACtC;AAAC,KACX;AAAA,EACJ,GAAG,CAAC,IAAA,EAAM,SAAS,UAAA,EAAY,OAAA,EAAS,YAAY,CAAC,CAAA;AASrD,EAAA,MAAM,sBACD,QAAA,CAAS,UAAA,IAAc,SAAS,UAAA,CAAW,WAAA,IAC5C,aAAa,QAAQ,CAAA;AAEzB,EAAA,MAAM,cAAA,GAAiB;AAAA,IACnB,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,iBAAA,EAAmB,EAAA;AAAA,IACnB,eAAA,EAAiB,CAAA;AAAA,IACjB,eAAA,EAAiB,aAAa,UAAU;AAAA,GAC5C;AAEA,EAAA,MAAM,cAAA,mBACFI,eAAA,CAACC,gBAAA,EAAA,EAAK,KAAA,EAAO,eAAA,EACR,QAAA,EAAA;AAAA,IAAA,SAAA,mBACGJ,cAAA;AAAA,MAACI,gBAAA;AAAA,MAAA;AAAA,QACG,KAAA,EAAO;AAAA,UACH,GAAG,cAAA;AAAA,UACH,cAAA,EAAgB,CAAA;AAAA,UAChB,cAAA,EAAgB,mBAAA;AAAA,UAChB,GAAI,QAAA,CAAS,SAAA,IAAa;AAAC,SAC/B;AAAA,QAEC,sBAAY,SAAS;AAAA;AAAA,KAC1B,GACA,IAAA;AAAA,oBAUJJ,cAAA,CAACI,oBAAK,KAAA,EAAO,EAAE,MAAM,CAAA,EAAG,cAAA,EAAgB,QAAA,EAAS,EAAI,QAAA,EAAS,CAAA;AAAA,IAE7D,UAAA,mBACGJ,cAAA;AAAA,MAACI,gBAAA;AAAA,MAAA;AAAA,QACG,KAAA,EAAO;AAAA,UACH,GAAG,cAAA;AAAA,UACH,gBAAA,EAAkB,CAAA;AAAA,UAClB,gBAAA,EAAkB,mBAAA;AAAA,UAClB,GAAI,QAAA,CAAS,UAAA,IAAc;AAAC,SAChC;AAAA,QAEC,sBAAY,UAAU;AAAA;AAAA,KAC3B,GACA;AAAA,GAAA,EACR,CAAA;AAGJ,EAAA,MAAM,gBAAA,GAAmBL,aAAA;AAAA,IACrB,MAAO,cAAA,IAAkB,MAAA,CAAO,IAAA,CAAK,cAAc,EAAE,MAAA,GAASM,WAAA,CAAa,cAAc,CAAA,GAAI,EAAC;AAAA,IAC9F,CAAC,cAAc;AAAA,GACnB;AAEA,EAAA,uBACIF,eAAA;AAAA,IAACG,iBAAA;AAAA,IAAA;AAAA,MACG,SAAA,EAAW,OAAA;AAAA,MACX,IAAA,EAAK,IAAA;AAAA,MACL,UAAA,EAAY,QAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACZ,KAAA,EAAO;AAAA,QACH,KAAA,EAAM,MAAA;AAAA,QAAQ,GAAA,EAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAKnB,GAAI,IAAA,GAAO,EAAE,WAAA,EAAa,CAAA,EAAG,cAAc,CAAA,EAAG,QAAA,EAAU,SAAA,EAAU,GAAI,EAAC;AAAA,QACvE,GAAI,QAAA,CAAS,SAAA,IAAa,EAAC;AAAA,QAC3B,GAAI,oBAAoB;AAAC,OAC7B;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,YAAA,mBACGH,eAAA,CAACC,gBAAA,EAAA,EAAK,KAAA,EAAO,EAAE,aAAA,EAAe,KAAA,EAAO,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,MAAA,EAAO,EAC5E,QAAA,EAAA;AAAA,UAAA,YAAA;AAAA,yCACAA,gBAAA,EAAA,EAAK,KAAA,EAAO,EAAE,IAAA,EAAM,CAAA,IAAM,QAAA,EAAA,cAAA,EAAe;AAAA,SAAA,EAC9C,CAAA,GACA,2BACAD,eAAA,CAAAI,mBAAA,EAAA,EACK,QAAA,EAAA;AAAA,UAAA,cAAA;AAAA,UACA;AAAA,SAAA,EACL,oBAEAJ,eAAA,CAAAI,mBAAA,EAAA,EACK,QAAA,EAAA;AAAA,UAAA,YAAA;AAAA,UACA;AAAA,SAAA,EACL,CAAA;AAAA,QAEH,UAAA,IAAc,OAAO,UAAA,KAAe,UAAA,oBAAcP,cAAA,CAACQ,2BAChD,QAAA,kBAAAR,cAAA,CAACS,2BAAA,EAAA,EAAsB,KAAA,EAAO,EAAC,GAAI,UAAA,GAAa,EAAC,UAAA,EAAY,UAAA,EAAU,GAAI,EAAC,EAAI,GAAI,QAAA,CAAS,UAAA,IAAc,EAAC,EAAE,EACzG,QAAA,EAAA,UAAA,EACL,CAAA,EACJ,CAAA;AAAA,QAEC,CAAC,6BAAaT,cAAA,CAACU,2BAAA,EAAA,EAAa,SAAkB,MAAA,EAAgB,KAAA,EAAO,QAAA,CAAS,KAAA,IAAS,MAAA,EAAW;AAAA;AAAA;AAAA,GACvG;AAER;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../../src/form/helpers/FormContainer/index.native.tsx"],"sourcesContent":["import React, { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { uniqueId } from \"lodash\";\nimport ErrorMessage from \"../ErrorMessage\";\nimport type {IKitsContainer} from \"@lmb-it/kitsconcerto-types\";\nimport {\n FormControl,\n FormControlHelper,\n FormControlHelperText,\n style as resolveStyle,\n} from \"@lmb-it/kitsconcertomobile\"\nimport { Label, Text, useKitsTheme } from \"../../../_compat\";\nimport {useResolvedElementStyles, useThemedFont} from \"@lmb-it/kitsconcerto/hooks\";\n\n/**\n * KitsContainer (native) — wraps all form inputs with label, addons, helper\n * text, and errors. Mirror of the web variant: a pure renderer that does NO\n * independent theme lookup. Every slot style comes from `elementStyles`\n * passed by the parent input (already merged through the\n * FormElement < Input/Select < InputText/DropdownSelect/… < per-instance slots\n * chain by the parent's `useComponentDefaults` call).\n *\n * Addon rendering is inlined here (matches web FormContainer). There is NO\n * `Addons` component on either platform anymore — the previous native Addons\n * helper re-resolved tokens and hardcoded `borderRadius / borderWidth /\n * padding / backgroundColor / borderColor` defaults that clobbered\n * `kitsTheme.components.*.leftAddon.style` overrides. Both bugs are fixed by\n * deleting the indirection.\n *\n * Element slots applied here (identical contract to web):\n * container → outer FormControl wrapper\n * label → Label component (plain Text path on native — see Label.native)\n * inputGroup → input group wrapper (around addons + input). On native this\n * wrapper carries the visual border that web gets from the\n * `.p-inputgroup` CSS class.\n * leftAddon → left addon View\n * rightAddon → right addon View\n * helperText → helper text below the group\n * error → error message below the group\n *\n * The `root` slot is NOT applied here — it is applied by the parent form\n * input component directly to the inner Input/Textarea element.\n */\nconst KitsContainer: FC<PropsWithChildren<IKitsContainer>> = (props) => {\n const {\n id,\n helperText,\n children,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n required,\n hideError,\n label,\n isFloatedLabel,\n containerStyle,\n disabled,\n bare,\n elementStyles: parentElementStyles,\n elementProps: parentElementProps,\n } = props;\n\n // Pure renderer: resolve the elementStyles passed in by the parent.\n // No `useComponentDefaults('FormContainer', …)` lookup — that key is\n // intentionally not part of the consumer-facing theme contract.\n const elStyles = useResolvedElementStyles(parentElementStyles || {});\n // Slot `props` — the web twin of this spreads them onto the DOM nodes.\n // On native `className` has no meaning, so it is dropped here; everything\n // else (testID, accessibility*, pointerEvents, …) is a legitimate View\n // prop and is forwarded. Same slot contract, honest about the platform.\n const elProps = parentElementProps || {};\n const stripClassName = (slot?: Record<string, any>) => {\n if (!slot) return {};\n const {className: _ignoredOnNative, ...rest} = slot;\n return rest;\n };\n const containerSlotProps = stripClassName(elProps.container);\n const inputGroupSlotProps = stripClassName(elProps.inputGroup);\n const { resolveToken } = useKitsTheme();\n const themedFont = useThemedFont('body');\n\n // Generate a unique element ID (for parity with web; not used in native labels)\n const elementId = id ? `${id}_element` : uniqueId(\"element_\");\n\n // Derive label placement from the label prop\n const placement = useMemo(() => {\n if (label && typeof label === 'object' && 'placement' in label) {\n return label.placement; // \"RL\" | \"B\" | \"T\"\n }\n return \"T\"; // default: top\n }, [label]);\n\n // Determine layout direction based on placement\n // T = top (column, label first), B = bottom (column-reverse), RL = side-by-side (row)\n const isHorizontal = placement === \"RL\";\n const isBottom = placement === \"B\";\n\n // Label uses the plain Text path (NOT the FormControlLabel path) because\n // @lmb-it/kitsconcertomobile's FormControlLabelText strips arbitrary\n // inline styles, which broke `kitsTheme.components.Input.label.style`\n // overrides on native. The plain Text path forwards `style` directly.\n const labelElement = !isFloatedLabel ? (\n <Label label={label} elementId={elementId} required={required} style={elStyles.label || undefined} />\n ) : null;\n\n /**\n * Inline addon renderer. Mirrors the dispatch web uses in FormContainer\n * (string → text, ReactElement → element) AND adds the function-arg\n * branch native needs because lucide-react-native icons are passed as\n * functions `(props) => <Icon …/>`. The function-arg branch never runs\n * on web (web never goes through this code) so it cannot affect web.\n */\n const renderAddon = (\n addon: IKitsContainer[\"leftAddon\"] | IKitsContainer[\"rightAddon\"],\n ) => {\n if (!addon) return null;\n if (typeof addon === \"string\" || typeof addon === \"number\") {\n return <Text fontSize={14}>{addon}</Text>;\n }\n if (typeof addon === \"function\") {\n return (addon as (args: { size: number }) => React.ReactNode)({ size: 16 });\n }\n if (React.isValidElement(addon)) {\n return addon;\n }\n return null;\n };\n\n // Resolved inputGroup wrapper style. The default theme provides\n // `Input.inputGroup.style.{borderColor, borderRadius, borderWidth, height}`\n // — these are what give the group its visual frame. Defaults are layered\n // *under* the user's resolved style, so a per-instance override always wins.\n //\n // The `invalid` border color is applied as a fallback default (after\n // theme defaults, before user `inputGroup.borderColor` override). When\n // `bare` is set, the whole frame is suppressed (matches web's\n // `bareInputGroupStyle`).\n const inputGroupStyle = useMemo(() => {\n if (bare) {\n // Bare mode (FilePicker, Radio, Checkbox group, …): drop ALL\n // inputGroup chrome including `height: 52` from the theme. Web's\n // FormContainer does the same — it passes `style={{}}` when\n // bare (see helpers/FormContainer/index.web.tsx, the bare\n // branch of the row Flex). Without this, the non-classic file\n // uploader's 200px dashed drop zone was being squashed to 52px.\n return {\n width: \"100%\" as const,\n borderWidth: 0,\n borderRadius: 0,\n overflow: \"visible\" as const,\n };\n }\n const userStyle = elStyles.inputGroup || {};\n const userOverrodeBorderColor = \"borderColor\" in userStyle;\n return {\n width: \"100%\" as const,\n flexDirection: \"row\" as const,\n alignItems: \"stretch\" as const,\n overflow: \"hidden\" as const,\n ...userStyle,\n ...(invalid && !userOverrodeBorderColor\n ? { borderColor: resolveToken(\"danger\") }\n : {}),\n };\n }, [bare, elStyles.inputGroup, invalid, resolveToken]);\n\n // Addon baseline chrome — mirrors what PrimeReact's `.p-inputgroup-addon`\n // CSS class gives web addons (gray fill + horizontal padding + 1px\n // separator border on the input-facing edge). On web these defaults\n // come from CSS; on native we must apply them inline. Theme overrides\n // (`elStyles.leftAddon` / `rightAddon`) are spread LAST so per-instance\n // values always win. The separator border colour falls back to the\n // inputGroup border colour for visual continuity.\n const addonSeparatorColor = (\n (elStyles.inputGroup && elStyles.inputGroup.borderColor) ||\n resolveToken(\"border\")\n );\n const addonBaseStyle = {\n alignItems: \"center\" as const,\n justifyContent: \"center\" as const,\n paddingHorizontal: 12,\n paddingVertical: 8,\n backgroundColor: resolveToken(\"bg-input\"),\n };\n\n const contentElement = (\n <View style={inputGroupStyle} {...inputGroupSlotProps}>\n {leftAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderEndWidth: 1,\n borderEndColor: addonSeparatorColor,\n ...(elStyles.leftAddon || {}),\n }}\n >\n {renderAddon(leftAddon)}\n </View>\n ) : null}\n\n {/* `justifyContent: 'center'` vertically centres the inner Input\n inside the 52px-tall inputGroup (matching web, where flex\n items default to vertical alignment via the inputGroup row\n + the input's intrinsic line-box centring). Without this,\n placeholders and selected values sat near the top edge of\n the input. Tall children that already fill the height\n (textarea) are unaffected because `justifyContent: 'center'`\n is a no-op on items that match the parent's cross-axis. */}\n <View style={{ flex: 1, justifyContent: 'center' }}>{children}</View>\n\n {rightAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderStartWidth: 1,\n borderStartColor: addonSeparatorColor,\n ...(elStyles.rightAddon || {}),\n }}\n >\n {renderAddon(rightAddon)}\n </View>\n ) : null}\n </View>\n );\n\n const containerRnStyle = useMemo(\n () => (containerStyle && Object.keys(containerStyle).length ? resolveStyle(containerStyle) : {}),\n [containerStyle],\n );\n\n return(\n <FormControl\n isInvalid={invalid}\n size=\"md\"\n isDisabled={disabled}\n isReadOnly={disabled}\n isRequired={required}\n {...containerSlotProps}\n style={{\n width:'100%', gap: 4,\n // `bare` strips the container's DEFAULT frame, but must not\n // override an explicit `container` slot. Spread it FIRST so a\n // user's borderRadius / borderWidth / overflow (e.g. an Object\n // or Group styled as a card) wins over the reset.\n ...(bare ? { borderWidth: 0, borderRadius: 0, overflow: 'visible' } : {}),\n ...(elStyles.container || {}),\n ...(containerRnStyle || {}),\n }}\n >\n {isHorizontal ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: '100%' }}>\n {labelElement}\n <View style={{ flex: 1 }}>{contentElement}</View>\n </View>\n ) : isBottom ? (\n <>\n {contentElement}\n {labelElement}\n </>\n ) : (\n <>\n {labelElement}\n {contentElement}\n </>\n )}\n {helperText && typeof helperText !== \"function\" && <FormControlHelper>\n <FormControlHelperText style={{...(themedFont ? {fontFamily: themedFont} : {}), ...(elStyles.helperText || {})}}>\n {helperText}\n </FormControlHelperText>\n </FormControlHelper>}\n\n {!hideError && <ErrorMessage invalid={invalid} errors={errors} style={elStyles.error || undefined} />}\n </FormControl>\n )\n};\n\nexport default KitsContainer;\n"],"names":["useResolvedElementStyles","useKitsTheme","useThemedFont","uniqueId","useMemo","jsx","Label","Text","jsxs","View","resolveStyle","FormControl","Fragment","FormControlHelper","FormControlHelperText","ErrorMessage"],"mappings":"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"}
@@ -108,9 +108,18 @@ const KitsContainer = (props) => {
108
108
  containerStyle,
109
109
  disabled,
110
110
  bare,
111
- elementStyles: parentElementStyles
111
+ elementStyles: parentElementStyles,
112
+ elementProps: parentElementProps
112
113
  } = props;
113
114
  const elStyles = useResolvedElementStyles(parentElementStyles || {});
115
+ const elProps = parentElementProps || {};
116
+ const stripClassName = (slot) => {
117
+ if (!slot) return {};
118
+ const { className: _ignoredOnNative, ...rest } = slot;
119
+ return rest;
120
+ };
121
+ const containerSlotProps = stripClassName(elProps.container);
122
+ const inputGroupSlotProps = stripClassName(elProps.inputGroup);
114
123
  const { resolveToken } = useKitsTheme();
115
124
  const themedFont = useThemedFont("body");
116
125
  const elementId = id ? `${id}_element` : uniqueId("element_");
@@ -164,7 +173,7 @@ const KitsContainer = (props) => {
164
173
  paddingVertical: 8,
165
174
  backgroundColor: resolveToken("bg-input")
166
175
  };
167
- const contentElement = /* @__PURE__ */ jsxs(View, { style: inputGroupStyle, children: [
176
+ const contentElement = /* @__PURE__ */ jsxs(View, { style: inputGroupStyle, ...inputGroupSlotProps, children: [
168
177
  leftAddon ? /* @__PURE__ */ jsx(
169
178
  View,
170
179
  {
@@ -203,6 +212,7 @@ const KitsContainer = (props) => {
203
212
  isDisabled: disabled,
204
213
  isReadOnly: disabled,
205
214
  isRequired: required,
215
+ ...containerSlotProps,
206
216
  style: {
207
217
  width: "100%",
208
218
  gap: 4,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../src/form/helpers/FormContainer/index.native.tsx"],"sourcesContent":["import React, { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { uniqueId } from \"lodash\";\nimport ErrorMessage from \"../ErrorMessage\";\nimport type {IKitsContainer} from \"@lmb-it/kitsconcerto-types\";\nimport {\n FormControl,\n FormControlHelper,\n FormControlHelperText,\n style as resolveStyle,\n} from \"@lmb-it/kitsconcertomobile\"\nimport { Label, Text, useKitsTheme } from \"../../../_compat\";\nimport {useResolvedElementStyles, useThemedFont} from \"@lmb-it/kitsconcerto/hooks\";\n\n/**\n * KitsContainer (native) — wraps all form inputs with label, addons, helper\n * text, and errors. Mirror of the web variant: a pure renderer that does NO\n * independent theme lookup. Every slot style comes from `elementStyles`\n * passed by the parent input (already merged through the\n * FormElement < Input/Select < InputText/DropdownSelect/… < per-instance slots\n * chain by the parent's `useComponentDefaults` call).\n *\n * Addon rendering is inlined here (matches web FormContainer). There is NO\n * `Addons` component on either platform anymore — the previous native Addons\n * helper re-resolved tokens and hardcoded `borderRadius / borderWidth /\n * padding / backgroundColor / borderColor` defaults that clobbered\n * `kitsTheme.components.*.leftAddon.style` overrides. Both bugs are fixed by\n * deleting the indirection.\n *\n * Element slots applied here (identical contract to web):\n * container → outer FormControl wrapper\n * label → Label component (plain Text path on native — see Label.native)\n * inputGroup → input group wrapper (around addons + input). On native this\n * wrapper carries the visual border that web gets from the\n * `.p-inputgroup` CSS class.\n * leftAddon → left addon View\n * rightAddon → right addon View\n * helperText → helper text below the group\n * error → error message below the group\n *\n * The `root` slot is NOT applied here — it is applied by the parent form\n * input component directly to the inner Input/Textarea element.\n */\nconst KitsContainer: FC<PropsWithChildren<IKitsContainer>> = (props) => {\n const {\n id,\n helperText,\n children,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n required,\n hideError,\n label,\n isFloatedLabel,\n containerStyle,\n disabled,\n bare,\n elementStyles: parentElementStyles,\n } = props;\n\n // Pure renderer: resolve the elementStyles passed in by the parent.\n // No `useComponentDefaults('FormContainer', …)` lookup — that key is\n // intentionally not part of the consumer-facing theme contract.\n const elStyles = useResolvedElementStyles(parentElementStyles || {});\n const { resolveToken } = useKitsTheme();\n const themedFont = useThemedFont('body');\n\n // Generate a unique element ID (for parity with web; not used in native labels)\n const elementId = id ? `${id}_element` : uniqueId(\"element_\");\n\n // Derive label placement from the label prop\n const placement = useMemo(() => {\n if (label && typeof label === 'object' && 'placement' in label) {\n return label.placement; // \"RL\" | \"B\" | \"T\"\n }\n return \"T\"; // default: top\n }, [label]);\n\n // Determine layout direction based on placement\n // T = top (column, label first), B = bottom (column-reverse), RL = side-by-side (row)\n const isHorizontal = placement === \"RL\";\n const isBottom = placement === \"B\";\n\n // Label uses the plain Text path (NOT the FormControlLabel path) because\n // @lmb-it/kitsconcertomobile's FormControlLabelText strips arbitrary\n // inline styles, which broke `kitsTheme.components.Input.label.style`\n // overrides on native. The plain Text path forwards `style` directly.\n const labelElement = !isFloatedLabel ? (\n <Label label={label} elementId={elementId} required={required} style={elStyles.label || undefined} />\n ) : null;\n\n /**\n * Inline addon renderer. Mirrors the dispatch web uses in FormContainer\n * (string → text, ReactElement → element) AND adds the function-arg\n * branch native needs because lucide-react-native icons are passed as\n * functions `(props) => <Icon …/>`. The function-arg branch never runs\n * on web (web never goes through this code) so it cannot affect web.\n */\n const renderAddon = (\n addon: IKitsContainer[\"leftAddon\"] | IKitsContainer[\"rightAddon\"],\n ) => {\n if (!addon) return null;\n if (typeof addon === \"string\" || typeof addon === \"number\") {\n return <Text fontSize={14}>{addon}</Text>;\n }\n if (typeof addon === \"function\") {\n return (addon as (args: { size: number }) => React.ReactNode)({ size: 16 });\n }\n if (React.isValidElement(addon)) {\n return addon;\n }\n return null;\n };\n\n // Resolved inputGroup wrapper style. The default theme provides\n // `Input.inputGroup.style.{borderColor, borderRadius, borderWidth, height}`\n // — these are what give the group its visual frame. Defaults are layered\n // *under* the user's resolved style, so a per-instance override always wins.\n //\n // The `invalid` border color is applied as a fallback default (after\n // theme defaults, before user `inputGroup.borderColor` override). When\n // `bare` is set, the whole frame is suppressed (matches web's\n // `bareInputGroupStyle`).\n const inputGroupStyle = useMemo(() => {\n if (bare) {\n // Bare mode (FilePicker, Radio, Checkbox group, …): drop ALL\n // inputGroup chrome including `height: 52` from the theme. Web's\n // FormContainer does the same — it passes `style={{}}` when\n // bare (see helpers/FormContainer/index.web.tsx, the bare\n // branch of the row Flex). Without this, the non-classic file\n // uploader's 200px dashed drop zone was being squashed to 52px.\n return {\n width: \"100%\" as const,\n borderWidth: 0,\n borderRadius: 0,\n overflow: \"visible\" as const,\n };\n }\n const userStyle = elStyles.inputGroup || {};\n const userOverrodeBorderColor = \"borderColor\" in userStyle;\n return {\n width: \"100%\" as const,\n flexDirection: \"row\" as const,\n alignItems: \"stretch\" as const,\n overflow: \"hidden\" as const,\n ...userStyle,\n ...(invalid && !userOverrodeBorderColor\n ? { borderColor: resolveToken(\"danger\") }\n : {}),\n };\n }, [bare, elStyles.inputGroup, invalid, resolveToken]);\n\n // Addon baseline chrome — mirrors what PrimeReact's `.p-inputgroup-addon`\n // CSS class gives web addons (gray fill + horizontal padding + 1px\n // separator border on the input-facing edge). On web these defaults\n // come from CSS; on native we must apply them inline. Theme overrides\n // (`elStyles.leftAddon` / `rightAddon`) are spread LAST so per-instance\n // values always win. The separator border colour falls back to the\n // inputGroup border colour for visual continuity.\n const addonSeparatorColor = (\n (elStyles.inputGroup && elStyles.inputGroup.borderColor) ||\n resolveToken(\"border\")\n );\n const addonBaseStyle = {\n alignItems: \"center\" as const,\n justifyContent: \"center\" as const,\n paddingHorizontal: 12,\n paddingVertical: 8,\n backgroundColor: resolveToken(\"bg-input\"),\n };\n\n const contentElement = (\n <View style={inputGroupStyle}>\n {leftAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderEndWidth: 1,\n borderEndColor: addonSeparatorColor,\n ...(elStyles.leftAddon || {}),\n }}\n >\n {renderAddon(leftAddon)}\n </View>\n ) : null}\n\n {/* `justifyContent: 'center'` vertically centres the inner Input\n inside the 52px-tall inputGroup (matching web, where flex\n items default to vertical alignment via the inputGroup row\n + the input's intrinsic line-box centring). Without this,\n placeholders and selected values sat near the top edge of\n the input. Tall children that already fill the height\n (textarea) are unaffected because `justifyContent: 'center'`\n is a no-op on items that match the parent's cross-axis. */}\n <View style={{ flex: 1, justifyContent: 'center' }}>{children}</View>\n\n {rightAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderStartWidth: 1,\n borderStartColor: addonSeparatorColor,\n ...(elStyles.rightAddon || {}),\n }}\n >\n {renderAddon(rightAddon)}\n </View>\n ) : null}\n </View>\n );\n\n const containerRnStyle = useMemo(\n () => (containerStyle && Object.keys(containerStyle).length ? resolveStyle(containerStyle) : {}),\n [containerStyle],\n );\n\n return(\n <FormControl\n isInvalid={invalid}\n size=\"md\"\n isDisabled={disabled}\n isReadOnly={disabled}\n isRequired={required}\n style={{\n width:'100%', gap: 4,\n // `bare` strips the container's DEFAULT frame, but must not\n // override an explicit `container` slot. Spread it FIRST so a\n // user's borderRadius / borderWidth / overflow (e.g. an Object\n // or Group styled as a card) wins over the reset.\n ...(bare ? { borderWidth: 0, borderRadius: 0, overflow: 'visible' } : {}),\n ...(elStyles.container || {}),\n ...(containerRnStyle || {}),\n }}\n >\n {isHorizontal ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: '100%' }}>\n {labelElement}\n <View style={{ flex: 1 }}>{contentElement}</View>\n </View>\n ) : isBottom ? (\n <>\n {contentElement}\n {labelElement}\n </>\n ) : (\n <>\n {labelElement}\n {contentElement}\n </>\n )}\n {helperText && typeof helperText !== \"function\" && <FormControlHelper>\n <FormControlHelperText style={{...(themedFont ? {fontFamily: themedFont} : {}), ...(elStyles.helperText || {})}}>\n {helperText}\n </FormControlHelperText>\n </FormControlHelper>}\n\n {!hideError && <ErrorMessage invalid={invalid} errors={errors} style={elStyles.error || undefined} />}\n </FormControl>\n )\n};\n\nexport default KitsContainer;\n"],"names":["resolveStyle"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../src/form/helpers/FormContainer/index.native.tsx"],"sourcesContent":["import React, { type FC, type PropsWithChildren, useMemo } from \"react\";\nimport { View } from \"react-native\";\nimport { uniqueId } from \"lodash\";\nimport ErrorMessage from \"../ErrorMessage\";\nimport type {IKitsContainer} from \"@lmb-it/kitsconcerto-types\";\nimport {\n FormControl,\n FormControlHelper,\n FormControlHelperText,\n style as resolveStyle,\n} from \"@lmb-it/kitsconcertomobile\"\nimport { Label, Text, useKitsTheme } from \"../../../_compat\";\nimport {useResolvedElementStyles, useThemedFont} from \"@lmb-it/kitsconcerto/hooks\";\n\n/**\n * KitsContainer (native) — wraps all form inputs with label, addons, helper\n * text, and errors. Mirror of the web variant: a pure renderer that does NO\n * independent theme lookup. Every slot style comes from `elementStyles`\n * passed by the parent input (already merged through the\n * FormElement < Input/Select < InputText/DropdownSelect/… < per-instance slots\n * chain by the parent's `useComponentDefaults` call).\n *\n * Addon rendering is inlined here (matches web FormContainer). There is NO\n * `Addons` component on either platform anymore — the previous native Addons\n * helper re-resolved tokens and hardcoded `borderRadius / borderWidth /\n * padding / backgroundColor / borderColor` defaults that clobbered\n * `kitsTheme.components.*.leftAddon.style` overrides. Both bugs are fixed by\n * deleting the indirection.\n *\n * Element slots applied here (identical contract to web):\n * container → outer FormControl wrapper\n * label → Label component (plain Text path on native — see Label.native)\n * inputGroup → input group wrapper (around addons + input). On native this\n * wrapper carries the visual border that web gets from the\n * `.p-inputgroup` CSS class.\n * leftAddon → left addon View\n * rightAddon → right addon View\n * helperText → helper text below the group\n * error → error message below the group\n *\n * The `root` slot is NOT applied here — it is applied by the parent form\n * input component directly to the inner Input/Textarea element.\n */\nconst KitsContainer: FC<PropsWithChildren<IKitsContainer>> = (props) => {\n const {\n id,\n helperText,\n children,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n required,\n hideError,\n label,\n isFloatedLabel,\n containerStyle,\n disabled,\n bare,\n elementStyles: parentElementStyles,\n elementProps: parentElementProps,\n } = props;\n\n // Pure renderer: resolve the elementStyles passed in by the parent.\n // No `useComponentDefaults('FormContainer', …)` lookup — that key is\n // intentionally not part of the consumer-facing theme contract.\n const elStyles = useResolvedElementStyles(parentElementStyles || {});\n // Slot `props` — the web twin of this spreads them onto the DOM nodes.\n // On native `className` has no meaning, so it is dropped here; everything\n // else (testID, accessibility*, pointerEvents, …) is a legitimate View\n // prop and is forwarded. Same slot contract, honest about the platform.\n const elProps = parentElementProps || {};\n const stripClassName = (slot?: Record<string, any>) => {\n if (!slot) return {};\n const {className: _ignoredOnNative, ...rest} = slot;\n return rest;\n };\n const containerSlotProps = stripClassName(elProps.container);\n const inputGroupSlotProps = stripClassName(elProps.inputGroup);\n const { resolveToken } = useKitsTheme();\n const themedFont = useThemedFont('body');\n\n // Generate a unique element ID (for parity with web; not used in native labels)\n const elementId = id ? `${id}_element` : uniqueId(\"element_\");\n\n // Derive label placement from the label prop\n const placement = useMemo(() => {\n if (label && typeof label === 'object' && 'placement' in label) {\n return label.placement; // \"RL\" | \"B\" | \"T\"\n }\n return \"T\"; // default: top\n }, [label]);\n\n // Determine layout direction based on placement\n // T = top (column, label first), B = bottom (column-reverse), RL = side-by-side (row)\n const isHorizontal = placement === \"RL\";\n const isBottom = placement === \"B\";\n\n // Label uses the plain Text path (NOT the FormControlLabel path) because\n // @lmb-it/kitsconcertomobile's FormControlLabelText strips arbitrary\n // inline styles, which broke `kitsTheme.components.Input.label.style`\n // overrides on native. The plain Text path forwards `style` directly.\n const labelElement = !isFloatedLabel ? (\n <Label label={label} elementId={elementId} required={required} style={elStyles.label || undefined} />\n ) : null;\n\n /**\n * Inline addon renderer. Mirrors the dispatch web uses in FormContainer\n * (string → text, ReactElement → element) AND adds the function-arg\n * branch native needs because lucide-react-native icons are passed as\n * functions `(props) => <Icon …/>`. The function-arg branch never runs\n * on web (web never goes through this code) so it cannot affect web.\n */\n const renderAddon = (\n addon: IKitsContainer[\"leftAddon\"] | IKitsContainer[\"rightAddon\"],\n ) => {\n if (!addon) return null;\n if (typeof addon === \"string\" || typeof addon === \"number\") {\n return <Text fontSize={14}>{addon}</Text>;\n }\n if (typeof addon === \"function\") {\n return (addon as (args: { size: number }) => React.ReactNode)({ size: 16 });\n }\n if (React.isValidElement(addon)) {\n return addon;\n }\n return null;\n };\n\n // Resolved inputGroup wrapper style. The default theme provides\n // `Input.inputGroup.style.{borderColor, borderRadius, borderWidth, height}`\n // — these are what give the group its visual frame. Defaults are layered\n // *under* the user's resolved style, so a per-instance override always wins.\n //\n // The `invalid` border color is applied as a fallback default (after\n // theme defaults, before user `inputGroup.borderColor` override). When\n // `bare` is set, the whole frame is suppressed (matches web's\n // `bareInputGroupStyle`).\n const inputGroupStyle = useMemo(() => {\n if (bare) {\n // Bare mode (FilePicker, Radio, Checkbox group, …): drop ALL\n // inputGroup chrome including `height: 52` from the theme. Web's\n // FormContainer does the same — it passes `style={{}}` when\n // bare (see helpers/FormContainer/index.web.tsx, the bare\n // branch of the row Flex). Without this, the non-classic file\n // uploader's 200px dashed drop zone was being squashed to 52px.\n return {\n width: \"100%\" as const,\n borderWidth: 0,\n borderRadius: 0,\n overflow: \"visible\" as const,\n };\n }\n const userStyle = elStyles.inputGroup || {};\n const userOverrodeBorderColor = \"borderColor\" in userStyle;\n return {\n width: \"100%\" as const,\n flexDirection: \"row\" as const,\n alignItems: \"stretch\" as const,\n overflow: \"hidden\" as const,\n ...userStyle,\n ...(invalid && !userOverrodeBorderColor\n ? { borderColor: resolveToken(\"danger\") }\n : {}),\n };\n }, [bare, elStyles.inputGroup, invalid, resolveToken]);\n\n // Addon baseline chrome — mirrors what PrimeReact's `.p-inputgroup-addon`\n // CSS class gives web addons (gray fill + horizontal padding + 1px\n // separator border on the input-facing edge). On web these defaults\n // come from CSS; on native we must apply them inline. Theme overrides\n // (`elStyles.leftAddon` / `rightAddon`) are spread LAST so per-instance\n // values always win. The separator border colour falls back to the\n // inputGroup border colour for visual continuity.\n const addonSeparatorColor = (\n (elStyles.inputGroup && elStyles.inputGroup.borderColor) ||\n resolveToken(\"border\")\n );\n const addonBaseStyle = {\n alignItems: \"center\" as const,\n justifyContent: \"center\" as const,\n paddingHorizontal: 12,\n paddingVertical: 8,\n backgroundColor: resolveToken(\"bg-input\"),\n };\n\n const contentElement = (\n <View style={inputGroupStyle} {...inputGroupSlotProps}>\n {leftAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderEndWidth: 1,\n borderEndColor: addonSeparatorColor,\n ...(elStyles.leftAddon || {}),\n }}\n >\n {renderAddon(leftAddon)}\n </View>\n ) : null}\n\n {/* `justifyContent: 'center'` vertically centres the inner Input\n inside the 52px-tall inputGroup (matching web, where flex\n items default to vertical alignment via the inputGroup row\n + the input's intrinsic line-box centring). Without this,\n placeholders and selected values sat near the top edge of\n the input. Tall children that already fill the height\n (textarea) are unaffected because `justifyContent: 'center'`\n is a no-op on items that match the parent's cross-axis. */}\n <View style={{ flex: 1, justifyContent: 'center' }}>{children}</View>\n\n {rightAddon ? (\n <View\n style={{\n ...addonBaseStyle,\n borderStartWidth: 1,\n borderStartColor: addonSeparatorColor,\n ...(elStyles.rightAddon || {}),\n }}\n >\n {renderAddon(rightAddon)}\n </View>\n ) : null}\n </View>\n );\n\n const containerRnStyle = useMemo(\n () => (containerStyle && Object.keys(containerStyle).length ? resolveStyle(containerStyle) : {}),\n [containerStyle],\n );\n\n return(\n <FormControl\n isInvalid={invalid}\n size=\"md\"\n isDisabled={disabled}\n isReadOnly={disabled}\n isRequired={required}\n {...containerSlotProps}\n style={{\n width:'100%', gap: 4,\n // `bare` strips the container's DEFAULT frame, but must not\n // override an explicit `container` slot. Spread it FIRST so a\n // user's borderRadius / borderWidth / overflow (e.g. an Object\n // or Group styled as a card) wins over the reset.\n ...(bare ? { borderWidth: 0, borderRadius: 0, overflow: 'visible' } : {}),\n ...(elStyles.container || {}),\n ...(containerRnStyle || {}),\n }}\n >\n {isHorizontal ? (\n <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: '100%' }}>\n {labelElement}\n <View style={{ flex: 1 }}>{contentElement}</View>\n </View>\n ) : isBottom ? (\n <>\n {contentElement}\n {labelElement}\n </>\n ) : (\n <>\n {labelElement}\n {contentElement}\n </>\n )}\n {helperText && typeof helperText !== \"function\" && <FormControlHelper>\n <FormControlHelperText style={{...(themedFont ? {fontFamily: themedFont} : {}), ...(elStyles.helperText || {})}}>\n {helperText}\n </FormControlHelperText>\n </FormControlHelper>}\n\n {!hideError && <ErrorMessage invalid={invalid} errors={errors} style={elStyles.error || undefined} />}\n </FormControl>\n )\n};\n\nexport default KitsContainer;\n"],"names":["resolveStyle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAM,aAAA,GAAuD,CAAC,KAAA,KAAU;AACpE,EAAA,MAAM;AAAA,IACF,EAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,aAAA,EAAe,mBAAA;AAAA,IACf,YAAA,EAAc;AAAA,GAClB,GAAI,KAAA;AAKJ,EAAA,MAAM,QAAA,GAAW,wBAAA,CAAyB,mBAAA,IAAuB,EAAE,CAAA;AAKnE,EAAA,MAAM,OAAA,GAAU,sBAAsB,EAAC;AACvC,EAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KAA+B;AACnD,IAAA,IAAI,CAAC,IAAA,EAAM,OAAO,EAAC;AACnB,IAAA,MAAM,EAAC,SAAA,EAAW,gBAAA,EAAkB,GAAG,MAAI,GAAI,IAAA;AAC/C,IAAA,OAAO,IAAA;AAAA,EACX,CAAA;AACA,EAAA,MAAM,kBAAA,GAAqB,cAAA,CAAe,OAAA,CAAQ,SAAS,CAAA;AAC3D,EAAA,MAAM,mBAAA,GAAsB,cAAA,CAAe,OAAA,CAAQ,UAAU,CAAA;AAC7D,EAAA,MAAM,EAAE,YAAA,EAAa,GAAI,YAAA,EAAa;AACtC,EAAA,MAAM,UAAA,GAAa,cAAc,MAAM,CAAA;AAGvC,EAAA,MAAM,YAAY,EAAA,GAAK,CAAA,EAAG,EAAE,CAAA,QAAA,CAAA,GAAa,SAAS,UAAU,CAAA;AAG5D,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAM;AAC5B,IAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,eAAe,KAAA,EAAO;AAC5D,MAAA,OAAO,KAAA,CAAM,SAAA;AAAA,IACjB;AACA,IAAA,OAAO,GAAA;AAAA,EACX,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAIV,EAAA,MAAM,eAAe,SAAA,KAAc,IAAA;AACnC,EAAA,MAAM,WAAW,SAAA,KAAc,GAAA;AAM/B,EAAA,MAAM,YAAA,GAAe,CAAC,cAAA,mBAClB,GAAA,CAAC,KAAA,EAAA,EAAM,KAAA,EAAc,SAAA,EAAsB,QAAA,EAAoB,KAAA,EAAO,QAAA,CAAS,KAAA,IAAS,MAAA,EAAW,CAAA,GACnG,IAAA;AASJ,EAAA,MAAM,WAAA,GAAc,CAChB,KAAA,KACC;AACD,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,UAAU,QAAA,EAAU;AACxD,MAAA,uBAAO,GAAA,CAAC,IAAA,EAAA,EAAK,QAAA,EAAU,EAAA,EAAK,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,IACtC;AACA,IAAA,IAAI,OAAO,UAAU,UAAA,EAAY;AAC7B,MAAA,OAAQ,KAAA,CAAsD,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA;AAAA,IAC9E;AACA,IAAA,IAAI,KAAA,CAAM,cAAA,CAAe,KAAK,CAAA,EAAG;AAC7B,MAAA,OAAO,KAAA;AAAA,IACX;AACA,IAAA,OAAO,IAAA;AAAA,EACX,CAAA;AAWA,EAAA,MAAM,eAAA,GAAkB,QAAQ,MAAM;AAClC,IAAA,IAAI,IAAA,EAAM;AAON,MAAA,OAAO;AAAA,QACH,KAAA,EAAO,MAAA;AAAA,QACP,WAAA,EAAa,CAAA;AAAA,QACb,YAAA,EAAc,CAAA;AAAA,QACd,QAAA,EAAU;AAAA,OACd;AAAA,IACJ;AACA,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,UAAA,IAAc,EAAC;AAC1C,IAAA,MAAM,0BAA0B,aAAA,IAAiB,SAAA;AACjD,IAAA,OAAO;AAAA,MACH,KAAA,EAAO,MAAA;AAAA,MACP,aAAA,EAAe,KAAA;AAAA,MACf,UAAA,EAAY,SAAA;AAAA,MACZ,QAAA,EAAU,QAAA;AAAA,MACV,GAAG,SAAA;AAAA,MACH,GAAI,OAAA,IAAW,CAAC,uBAAA,GACV,EAAE,aAAa,YAAA,CAAa,QAAQ,CAAA,EAAE,GACtC;AAAC,KACX;AAAA,EACJ,GAAG,CAAC,IAAA,EAAM,SAAS,UAAA,EAAY,OAAA,EAAS,YAAY,CAAC,CAAA;AASrD,EAAA,MAAM,sBACD,QAAA,CAAS,UAAA,IAAc,SAAS,UAAA,CAAW,WAAA,IAC5C,aAAa,QAAQ,CAAA;AAEzB,EAAA,MAAM,cAAA,GAAiB;AAAA,IACnB,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,QAAA;AAAA,IAChB,iBAAA,EAAmB,EAAA;AAAA,IACnB,eAAA,EAAiB,CAAA;AAAA,IACjB,eAAA,EAAiB,aAAa,UAAU;AAAA,GAC5C;AAEA,EAAA,MAAM,iCACF,IAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAO,eAAA,EAAkB,GAAG,mBAAA,EAC7B,QAAA,EAAA;AAAA,IAAA,SAAA,mBACG,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACG,KAAA,EAAO;AAAA,UACH,GAAG,cAAA;AAAA,UACH,cAAA,EAAgB,CAAA;AAAA,UAChB,cAAA,EAAgB,mBAAA;AAAA,UAChB,GAAI,QAAA,CAAS,SAAA,IAAa;AAAC,SAC/B;AAAA,QAEC,sBAAY,SAAS;AAAA;AAAA,KAC1B,GACA,IAAA;AAAA,oBAUJ,GAAA,CAAC,QAAK,KAAA,EAAO,EAAE,MAAM,CAAA,EAAG,cAAA,EAAgB,QAAA,EAAS,EAAI,QAAA,EAAS,CAAA;AAAA,IAE7D,UAAA,mBACG,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACG,KAAA,EAAO;AAAA,UACH,GAAG,cAAA;AAAA,UACH,gBAAA,EAAkB,CAAA;AAAA,UAClB,gBAAA,EAAkB,mBAAA;AAAA,UAClB,GAAI,QAAA,CAAS,UAAA,IAAc;AAAC,SAChC;AAAA,QAEC,sBAAY,UAAU;AAAA;AAAA,KAC3B,GACA;AAAA,GAAA,EACR,CAAA;AAGJ,EAAA,MAAM,gBAAA,GAAmB,OAAA;AAAA,IACrB,MAAO,cAAA,IAAkB,MAAA,CAAO,IAAA,CAAK,cAAc,EAAE,MAAA,GAASA,KAAA,CAAa,cAAc,CAAA,GAAI,EAAC;AAAA,IAC9F,CAAC,cAAc;AAAA,GACnB;AAEA,EAAA,uBACI,IAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACG,SAAA,EAAW,OAAA;AAAA,MACX,IAAA,EAAK,IAAA;AAAA,MACL,UAAA,EAAY,QAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACX,GAAG,kBAAA;AAAA,MACJ,KAAA,EAAO;AAAA,QACH,KAAA,EAAM,MAAA;AAAA,QAAQ,GAAA,EAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAKnB,GAAI,IAAA,GAAO,EAAE,WAAA,EAAa,CAAA,EAAG,cAAc,CAAA,EAAG,QAAA,EAAU,SAAA,EAAU,GAAI,EAAC;AAAA,QACvE,GAAI,QAAA,CAAS,SAAA,IAAa,EAAC;AAAA,QAC3B,GAAI,oBAAoB;AAAC,OAC7B;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,YAAA,mBACG,IAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAO,EAAE,aAAA,EAAe,KAAA,EAAO,UAAA,EAAY,QAAA,EAAU,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,MAAA,EAAO,EAC5E,QAAA,EAAA;AAAA,UAAA,YAAA;AAAA,8BACA,IAAA,EAAA,EAAK,KAAA,EAAO,EAAE,IAAA,EAAM,CAAA,IAAM,QAAA,EAAA,cAAA,EAAe;AAAA,SAAA,EAC9C,CAAA,GACA,2BACA,IAAA,CAAA,QAAA,EAAA,EACK,QAAA,EAAA;AAAA,UAAA,cAAA;AAAA,UACA;AAAA,SAAA,EACL,oBAEA,IAAA,CAAA,QAAA,EAAA,EACK,QAAA,EAAA;AAAA,UAAA,YAAA;AAAA,UACA;AAAA,SAAA,EACL,CAAA;AAAA,QAEH,UAAA,IAAc,OAAO,UAAA,KAAe,UAAA,oBAAc,GAAA,CAAC,qBAChD,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAsB,KAAA,EAAO,EAAC,GAAI,UAAA,GAAa,EAAC,UAAA,EAAY,UAAA,EAAU,GAAI,EAAC,EAAI,GAAI,QAAA,CAAS,UAAA,IAAc,EAAC,EAAE,EACzG,QAAA,EAAA,UAAA,EACL,CAAA,EACJ,CAAA;AAAA,QAEC,CAAC,6BAAa,GAAA,CAAC,YAAA,EAAA,EAAa,SAAkB,MAAA,EAAgB,KAAA,EAAO,QAAA,CAAS,KAAA,IAAS,MAAA,EAAW;AAAA;AAAA;AAAA,GACvG;AAER;;;;"}
@@ -95,9 +95,13 @@ var useResolvedStyle = require('../../../hooks/useResolvedStyle.cjs');
95
95
  var KitsThemeProvider_native = require('../../../contexts/Theme/KitsThemeProvider.cjs');
96
96
 
97
97
  const KitsAutoComplete = ({ ref, ...rawProps }) => {
98
- const { mergedProps: props, themeStyle, elementStyles } = useComponentDefaults.default("AutoComplete", rawProps, "Select");
98
+ const { mergedProps: props, themeStyle, elementStyles, elementProps } = useComponentDefaults.default("AutoComplete", rawProps, "Select");
99
99
  const resolvedThemeStyle = useResolvedStyle.default(themeStyle);
100
100
  const resolvedRootStyle = useResolvedStyle.default(elementStyles?.root || {});
101
+ const resolvedTokenContainer = useResolvedStyle.default(elementStyles?.tokenContainer || {});
102
+ const resolvedToken = useResolvedStyle.default(elementStyles?.token || {});
103
+ const resolvedTokenIcon = useResolvedStyle.default(elementStyles?.tokenIcon || {});
104
+ const { wrapper: tokenBoxStyle, text: tokenLabelStyle } = useResolvedStyle.splitTextStyle(resolvedToken);
101
105
  const {
102
106
  id,
103
107
  rightAddon,
@@ -162,6 +166,10 @@ const KitsAutoComplete = ({ ref, ...rawProps }) => {
162
166
  optionGroupLabel: childrenKey ? labelKey : void 0,
163
167
  style: { width: "100%", borderRadius: 0, border: "none", backgroundColor: "transparent" },
164
168
  inputStyle: { flexDirection: "row", borderRadius: 0, border: "none", width: "100%", backgroundColor: "transparent", ...resolvedRootStyle || resolvedThemeStyle },
169
+ tokenContainerStyle: resolvedTokenContainer,
170
+ tokenStyle: tokenBoxStyle,
171
+ tokenLabelStyle,
172
+ tokenIconStyle: resolvedTokenIcon,
165
173
  onChange: (event) => {
166
174
  setInputValue(event.value);
167
175
  handleOnChange(event);
@@ -199,6 +207,7 @@ const KitsAutoComplete = ({ ref, ...rawProps }) => {
199
207
  label,
200
208
  containerStyle,
201
209
  elementStyles: overflowEscape,
210
+ elementProps,
202
211
  children: Element
203
212
  }
204
213
  );
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../../src/form/selects/AutoComplete/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport KitsContainer from \"../../helpers/FormContainer\";\nimport {AutoComplete, useSeparator} from \"@lmb-it/kitsconcertomobile\";\nimport type { IAutoCompleteElement } from \"@lmb-it/kitsconcerto-types\";\nimport { useAutoCompleteLogic } from \"../hooks/useAutoCompleteLogic\";\nimport { useComponentDefaults, useResolvedStyle } from \"../../../hooks\";\nimport { useKitsTheme } from \"../../../contexts/Theme\";\n\nconst KitsAutoComplete = ({ ref, ...rawProps }: IAutoCompleteElement) => {\n const { mergedProps: props, themeStyle, elementStyles } = useComponentDefaults('AutoComplete', rawProps, 'Select');\n const resolvedThemeStyle = useResolvedStyle(themeStyle);\n const resolvedRootStyle = useResolvedStyle(elementStyles?.root || {});\n const {\n id,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n label,\n hideError,\n disabled,\n required,\n isFloatedLabel,\n inputSize = \"md\",\n forceSelection,\n completeMethod,\n helperText,\n withArrow,\n placeholder,\n isMultiple,\n localProps,\n delay,\n minLength,\n selectionLimit,\n showEmptyMessage,\n emptyMessage,\n attached,\n containerStyle,\n } = props;\n\n const { nativeProps } = useSeparator<HTMLSelectElement>(props);\n\n const { resolveToken } = useKitsTheme();\n const primaryColor = resolveToken('primary');\n const borderColor = resolveToken('border');\n\n const {\n inputValue,\n setInputValue,\n filteredList,\n search,\n handleOnChange,\n list,\n childrenKey,\n labelKey,\n } = useAutoCompleteLogic({ isMultiple, forceSelection, completeMethod, ref });\n\n const hasThemeStyle = Object.keys(themeStyle).length > 0;\n\n\n const Element = <AutoComplete\n disabled={disabled}\n placeholder={placeholder}\n value={inputValue}\n forceSelection={forceSelection}\n suggestions={Array.isArray(filteredList) ? filteredList : list}\n completeMethod={search}\n dropdown={withArrow}\n multiple={isMultiple}\n field={labelKey}\n invalid={!!invalid}\n emptyMessage={emptyMessage ?? \"No results found\"}\n {...(delay != null ? { delay } : {})}\n {...(minLength != null ? { minLength } : {})}\n {...(selectionLimit != null ? { selectionLimit } : {})}\n showEmptyMessage={showEmptyMessage ?? true}\n optionGroupChildren={childrenKey ?? undefined}\n optionGroupLabel={childrenKey ? labelKey : undefined}\n style={{ width: \"100%\", borderRadius: 0, border:'none', backgroundColor:'transparent' }}\n inputStyle={{ flexDirection: \"row\", borderRadius: 0, border:'none', width: \"100%\",backgroundColor:'transparent', ...(resolvedRootStyle || resolvedThemeStyle) }}\n onChange={(event) => {\n setInputValue(event.value);\n handleOnChange(event);\n }}\n {...(localProps ?? {})}\n />\n\n if (attached) {\n return Element;\n }\n\n // KitsContainer's `inputGroup` wrapper defaults to `overflow: 'hidden'`\n // (so rounded borders clip the input cleanly). For AutoComplete that\n // would clip the floating suggestions panel back to the input's bounds\n // — the panel renders but is invisible, which is the \"list never\n // appears\" symptom on mobile. Force `overflow: 'visible'` on the\n // container chain so the panel can escape.\n const overflowEscape = {\n ...elementStyles,\n container: {\n ...(elementStyles?.container || {}),\n overflow: 'visible' as const,\n },\n inputGroup: {\n ...(elementStyles?.inputGroup || {}),\n overflow: 'visible' as const,\n },\n };\n\n return (\n <KitsContainer\n id={id}\n inputSize={inputSize}\n isFloatedLabel={isFloatedLabel}\n hideError={hideError}\n rightAddon={rightAddon}\n leftAddon={leftAddon}\n required={required}\n helperText={helperText}\n errors={errors}\n invalid={invalid}\n label={label}\n containerStyle={containerStyle}\n elementStyles={overflowEscape}\n >\n {Element}\n </KitsContainer>\n );\n};\n\nexport default KitsAutoComplete;\n"],"names":["useComponentDefaults","useResolvedStyle","useSeparator","useKitsTheme","useAutoCompleteLogic","jsx","AutoComplete","KitsContainer"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../../src/form/selects/AutoComplete/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport KitsContainer from \"../../helpers/FormContainer\";\nimport {AutoComplete, useSeparator} from \"@lmb-it/kitsconcertomobile\";\nimport type { IAutoCompleteElement } from \"@lmb-it/kitsconcerto-types\";\nimport { useAutoCompleteLogic } from \"../hooks/useAutoCompleteLogic\";\nimport { useComponentDefaults, useResolvedStyle } from \"../../../hooks\";\nimport { splitTextStyle } from \"../../../hooks/useResolvedStyle\";\nimport { useKitsTheme } from \"../../../contexts/Theme\";\n\nconst KitsAutoComplete = ({ ref, ...rawProps }: IAutoCompleteElement) => {\n const { mergedProps: props, themeStyle, elementStyles, elementProps } = useComponentDefaults('AutoComplete', rawProps, 'Select');\n const resolvedThemeStyle = useResolvedStyle(themeStyle);\n const resolvedRootStyle = useResolvedStyle(elementStyles?.root || {});\n /* ─── Chips field slots — the native half of the same contract ──────────\n `tokenContainer` is the field wrapper View that holds the chips and the\n TextInput (web: `ul.p-autocomplete-multiple-container`). `token` splits\n in two on native, because a React Native `View` cannot carry `color` or\n `fontSize` — the text half goes to the chip's `Text`, which is what the\n CSS cascade does for free on web. */\n const resolvedTokenContainer = useResolvedStyle(elementStyles?.tokenContainer || {});\n const resolvedToken = useResolvedStyle(elementStyles?.token || {});\n const resolvedTokenIcon = useResolvedStyle(elementStyles?.tokenIcon || {});\n const {wrapper: tokenBoxStyle, text: tokenLabelStyle} = splitTextStyle(resolvedToken);\n const {\n id,\n rightAddon,\n leftAddon,\n errors,\n invalid,\n label,\n hideError,\n disabled,\n required,\n isFloatedLabel,\n inputSize = \"md\",\n forceSelection,\n completeMethod,\n helperText,\n withArrow,\n placeholder,\n isMultiple,\n localProps,\n delay,\n minLength,\n selectionLimit,\n showEmptyMessage,\n emptyMessage,\n attached,\n containerStyle,\n } = props;\n\n const { nativeProps } = useSeparator<HTMLSelectElement>(props);\n\n const { resolveToken } = useKitsTheme();\n const primaryColor = resolveToken('primary');\n const borderColor = resolveToken('border');\n\n const {\n inputValue,\n setInputValue,\n filteredList,\n search,\n handleOnChange,\n list,\n childrenKey,\n labelKey,\n } = useAutoCompleteLogic({ isMultiple, forceSelection, completeMethod, ref });\n\n const hasThemeStyle = Object.keys(themeStyle).length > 0;\n\n\n const Element = <AutoComplete\n disabled={disabled}\n placeholder={placeholder}\n value={inputValue}\n forceSelection={forceSelection}\n suggestions={Array.isArray(filteredList) ? filteredList : list}\n completeMethod={search}\n dropdown={withArrow}\n multiple={isMultiple}\n field={labelKey}\n invalid={!!invalid}\n emptyMessage={emptyMessage ?? \"No results found\"}\n {...(delay != null ? { delay } : {})}\n {...(minLength != null ? { minLength } : {})}\n {...(selectionLimit != null ? { selectionLimit } : {})}\n showEmptyMessage={showEmptyMessage ?? true}\n optionGroupChildren={childrenKey ?? undefined}\n optionGroupLabel={childrenKey ? labelKey : undefined}\n style={{ width: \"100%\", borderRadius: 0, border:'none', backgroundColor:'transparent' }}\n inputStyle={{ flexDirection: \"row\", borderRadius: 0, border:'none', width: \"100%\",backgroundColor:'transparent', ...(resolvedRootStyle || resolvedThemeStyle) }}\n tokenContainerStyle={resolvedTokenContainer}\n tokenStyle={tokenBoxStyle}\n tokenLabelStyle={tokenLabelStyle}\n tokenIconStyle={resolvedTokenIcon}\n onChange={(event) => {\n setInputValue(event.value);\n handleOnChange(event);\n }}\n {...(localProps ?? {})}\n />\n\n if (attached) {\n return Element;\n }\n\n // KitsContainer's `inputGroup` wrapper defaults to `overflow: 'hidden'`\n // (so rounded borders clip the input cleanly). For AutoComplete that\n // would clip the floating suggestions panel back to the input's bounds\n // — the panel renders but is invisible, which is the \"list never\n // appears\" symptom on mobile. Force `overflow: 'visible'` on the\n // container chain so the panel can escape.\n const overflowEscape = {\n ...elementStyles,\n container: {\n ...(elementStyles?.container || {}),\n overflow: 'visible' as const,\n },\n inputGroup: {\n ...(elementStyles?.inputGroup || {}),\n overflow: 'visible' as const,\n },\n };\n\n return (\n <KitsContainer\n id={id}\n inputSize={inputSize}\n isFloatedLabel={isFloatedLabel}\n hideError={hideError}\n rightAddon={rightAddon}\n leftAddon={leftAddon}\n required={required}\n helperText={helperText}\n errors={errors}\n invalid={invalid}\n label={label}\n containerStyle={containerStyle}\n elementStyles={overflowEscape}\n elementProps={elementProps}\n >\n {Element}\n </KitsContainer>\n );\n};\n\nexport default KitsAutoComplete;\n"],"names":["useComponentDefaults","useResolvedStyle","splitTextStyle","useSeparator","useKitsTheme","useAutoCompleteLogic","jsx","AutoComplete","KitsContainer"],"mappings":"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"}
@@ -87,13 +87,17 @@ import '../../../contexts/DialogContext.js';
87
87
  import '../../../contexts/PermissionsContext.js';
88
88
  import '../../../contexts/BreadcrumbContext.js';
89
89
  import useComponentDefaults from '../../../hooks/useComponentDefaults.js';
90
- import useResolvedStyle from '../../../hooks/useResolvedStyle.js';
90
+ import useResolvedStyle, { splitTextStyle } from '../../../hooks/useResolvedStyle.js';
91
91
  import { useKitsTheme } from '../../../contexts/Theme/KitsThemeProvider.js';
92
92
 
93
93
  const KitsAutoComplete = ({ ref, ...rawProps }) => {
94
- const { mergedProps: props, themeStyle, elementStyles } = useComponentDefaults("AutoComplete", rawProps, "Select");
94
+ const { mergedProps: props, themeStyle, elementStyles, elementProps } = useComponentDefaults("AutoComplete", rawProps, "Select");
95
95
  const resolvedThemeStyle = useResolvedStyle(themeStyle);
96
96
  const resolvedRootStyle = useResolvedStyle(elementStyles?.root || {});
97
+ const resolvedTokenContainer = useResolvedStyle(elementStyles?.tokenContainer || {});
98
+ const resolvedToken = useResolvedStyle(elementStyles?.token || {});
99
+ const resolvedTokenIcon = useResolvedStyle(elementStyles?.tokenIcon || {});
100
+ const { wrapper: tokenBoxStyle, text: tokenLabelStyle } = splitTextStyle(resolvedToken);
97
101
  const {
98
102
  id,
99
103
  rightAddon,
@@ -158,6 +162,10 @@ const KitsAutoComplete = ({ ref, ...rawProps }) => {
158
162
  optionGroupLabel: childrenKey ? labelKey : void 0,
159
163
  style: { width: "100%", borderRadius: 0, border: "none", backgroundColor: "transparent" },
160
164
  inputStyle: { flexDirection: "row", borderRadius: 0, border: "none", width: "100%", backgroundColor: "transparent", ...resolvedRootStyle || resolvedThemeStyle },
165
+ tokenContainerStyle: resolvedTokenContainer,
166
+ tokenStyle: tokenBoxStyle,
167
+ tokenLabelStyle,
168
+ tokenIconStyle: resolvedTokenIcon,
161
169
  onChange: (event) => {
162
170
  setInputValue(event.value);
163
171
  handleOnChange(event);
@@ -195,6 +203,7 @@ const KitsAutoComplete = ({ ref, ...rawProps }) => {
195
203
  label,
196
204
  containerStyle,
197
205
  elementStyles: overflowEscape,
206
+ elementProps,
198
207
  children: Element
199
208
  }
200
209
  );