@lmb-it/kitsconcerto-native 0.1.284 → 0.1.285
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/apps/mobile/src/Core/AutoComplete/index.cjs +12 -4
- package/apps/mobile/src/Core/AutoComplete/index.cjs.map +1 -1
- package/apps/mobile/src/Core/AutoComplete/index.js +12 -4
- package/apps/mobile/src/Core/AutoComplete/index.js.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.cjs +7 -4
- package/apps/mobile/src/Core/MultiSelect/index.cjs.map +1 -1
- package/apps/mobile/src/Core/MultiSelect/index.js +7 -4
- package/apps/mobile/src/Core/MultiSelect/index.js.map +1 -1
- package/form/helpers/FormContainer/index.cjs +12 -2
- package/form/helpers/FormContainer/index.cjs.map +1 -1
- package/form/helpers/FormContainer/index.js +12 -2
- package/form/helpers/FormContainer/index.js.map +1 -1
- package/form/selects/AutoComplete/index.cjs +10 -1
- package/form/selects/AutoComplete/index.cjs.map +1 -1
- package/form/selects/AutoComplete/index.js +11 -2
- package/form/selects/AutoComplete/index.js.map +1 -1
- package/form/selects/MultiSelect/index.cjs +8 -1
- package/form/selects/MultiSelect/index.cjs.map +1 -1
- package/form/selects/MultiSelect/index.js +9 -2
- package/form/selects/MultiSelect/index.js.map +1 -1
- package/hooks/useComponentDefaults.cjs +50 -8
- package/hooks/useComponentDefaults.cjs.map +1 -1
- package/hooks/useComponentDefaults.js +50 -8
- package/hooks/useComponentDefaults.js.map +1 -1
- package/index.d.ts +102 -15
- package/package.json +1 -1
- package/packages/types/src/Theme/defaultTheme.cjs +24 -4
- package/packages/types/src/Theme/defaultTheme.cjs.map +1 -1
- package/packages/types/src/Theme/defaultTheme.js +24 -4
- package/packages/types/src/Theme/defaultTheme.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../../../../../apps/mobile/src/Core/MultiSelect/index.tsx"],"sourcesContent":["import React, { useMemo, useRef, useState } from 'react';\nimport {\n View,\n Text,\n TouchableOpacity,\n Modal,\n FlatList,\n TextInput,\n StyleSheet,\n Pressable,\n ActivityIndicator,\n Dimensions,\n} from 'react-native';\nimport { readerEdge } from '../../Factory/helpers/readerEdge';\nimport { resolveThemeTokenForNative } from '../../Factory/helpers/style';\n\nexport type MultiSelectChangeEvent<T> = React.ChangeEvent<{\n value: T[];\n}>;\n\nexport interface MultiSelectProps<T> {\n value?: T[] | null;\n onChange?: (e: MultiSelectChangeEvent<T>, selectedItems: T[]) => void;\n isModal?: boolean;\n\n options?: T[];\n\n optionLabel?: keyof T | string;\n optionValue?: keyof T | string;\n\n optionGroupLabel?: keyof T | string;\n optionGroupChildren?: keyof T | string;\n\n placeholder?: string;\n disabled?: boolean;\n loading?: boolean;\n filter?: boolean;\n emptyFilterMessage?: string;\n /**\n * Placeholder for the panel's filter field, already written in the reader's\n * language by the KitsConcerto wrapper — this component lives in\n * `apps/mobile`, which `packages/ui` imports, so it cannot translate.\n */\n filterPlaceholder?: string;\n /** Reader's direction, from the wrapper's `useLanguage().isRTL`. */\n isRTL?: boolean;\n /**\n * Font family the app's theme names for body text, resolved by the wrapper.\n * React Native does not cascade fontFamily through Views, so each text sink\n * must set it — see the Dropdown's own note.\n */\n fontFamily?: string;\n /**\n * Open the options in a popup that owns the screen instead of a panel\n * anchored to the trigger. Default false — see the Dropdown's own `popup`\n * for why the anchor is the thing being escaped.\n */\n popup?: boolean;\n /**\n * Supplies the popup's container. Injected by the KitsConcerto wrapper: the\n * container is this library's `KitsDialogControlled`, which lives in\n * `packages/ui`, and `packages/ui` imports THIS file.\n */\n renderPopup?: (args: {\n visible: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n }) => React.ReactNode;\n /** Title for the popup header. */\n popupTitle?: React.ReactNode;\n\n display?: 'comma' | 'chip';\n maxSelectedLabels?: number;\n\n itemTemplate?: (item: T) => React.ReactElement;\n selectedItemTemplate?: (item: T) => React.ReactElement;\n style?: import('react-native').ViewStyle;\n}\n\nconst t = resolveThemeTokenForNative;\n\nconst TEXT_STYLE_KEYS = new Set([\n 'fontSize', 'fontFamily', 'fontWeight', 'fontStyle',\n 'color', 'letterSpacing', 'lineHeight', 'textAlign',\n 'textDecorationLine', 'textTransform',\n]);\n\nfunction splitStyle(combined?: any): { viewStyle?: any; textStyle?: any } {\n if (!combined) return {};\n const view: Record<string, any> = {};\n const text: Record<string, any> = {};\n for (const [k, v] of Object.entries(combined)) {\n if (TEXT_STYLE_KEYS.has(k)) text[k] = v;\n else view[k] = v;\n }\n return {\n viewStyle: Object.keys(view).length ? view : undefined,\n textStyle: Object.keys(text).length ? text : undefined,\n };\n}\n\nexport default function MultiSelect<T>(props: MultiSelectProps<T>) {\n const {\n value,\n onChange,\n options = [],\n optionLabel,\n optionValue,\n optionGroupLabel,\n optionGroupChildren,\n isModal = false,\n placeholder = 'Select',\n disabled,\n loading,\n filter,\n // ⚠️ English literals of last resort, not translations — the wrapper always\n // passes the reader's own sentence. These only apply when this component is\n // used directly from `apps/mobile`, so a panel can never render blank.\n emptyFilterMessage = 'No results found',\n filterPlaceholder = 'Search...',\n isRTL = false,\n fontFamily,\n popup = false,\n renderPopup,\n popupTitle,\n display = 'chip',\n maxSelectedLabels = 10,\n itemTemplate,\n selectedItemTemplate,\n style: externalStyle,\n } = props;\n\n /* Physical edges to write so content lands where the reader starts. */\n const edge = readerEdge(isRTL);\n\n const triggerRef = useRef<View>(null);\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [triggerLayout, setTriggerLayout] = useState<{\n x: number; y: number; width: number; height: number;\n } | null>(null);\n\n const close = () => setOpen(false);\n\n const toggleOpen = () => {\n if (disabled) return;\n if (open) {\n setOpen(false);\n return;\n }\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerLayout({ x, y, width, height });\n setOpen(true);\n });\n };\n\n const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);\n\n const colors = {\n border: t('border') || t('gray.300'),\n borderFocus: t('primary'),\n bg: t('surface-card') || '#fff',\n disabledBg: t('surface-ground') || t('gray.100'),\n placeholder: t('text-secondary') || t('gray.400'),\n text: t('text') || t('gray.800'),\n textSecondary: t('text-secondary') || t('gray.500'),\n chipBg: t('primary.100') || t('indigo.100'),\n chipText: t('primary.700') || t('indigo.700'),\n chipRemove: t('primary.500') || t('indigo.500'),\n chipMoreBg: t('surface-ground') || t('gray.100'),\n headerBorder: t('border') || t('gray.200'),\n groupBg: t('surface-ground') || t('gray.50'),\n groupBorder: t('border') || t('gray.200'),\n itemBorder: t('surface-ground') || t('gray.100'),\n itemSelectedBg: t('highlight-bg') || t('indigo.50'),\n itemSelectedText: t('primary.700') || t('indigo.700'),\n checkboxBorder: t('border') || t('gray.300'),\n checkboxChecked: t('primary'),\n invalidBorder: t('danger') || t('red.500'),\n searchBg: t('surface-ground') || t('gray.50'),\n };\n\n const getValue = (item: T, key?: keyof T | string) =>\n key ? (item as any)[key] : item;\n\n const getLabel = (item: T, key?: keyof T | string) =>\n String(key ? (item as any)[key] : item);\n\n const selectedValues = Array.isArray(value) ? value : [];\n\n // Build display items: flat list with optional group headers\n const displayItems: { type: 'group' | 'item'; data: any }[] = useMemo(() => {\n if (optionGroupLabel && optionGroupChildren) {\n const result: { type: 'group' | 'item'; data: any }[] = [];\n options.forEach((group: any) => {\n result.push({ type: 'group', data: group });\n const children = group[optionGroupChildren] ?? [];\n children.forEach((child: any) => result.push({ type: 'item', data: child }));\n });\n return result;\n }\n return options.map((item) => ({ type: 'item' as const, data: item }));\n }, [options, optionGroupLabel, optionGroupChildren]);\n\n const filtered = useMemo(() => {\n if (!filter || !query) return displayItems;\n return displayItems.filter((entry) => {\n if (entry.type === 'group') return true; // keep group headers\n return getLabel(entry.data, optionLabel)\n .toLowerCase()\n .includes(query.toLowerCase());\n });\n }, [query, displayItems]);\n\n const isSelected = (item: T) =>\n selectedValues.some(\n (v) => getValue(v, optionValue) === getValue(item, optionValue),\n );\n\n const toggleItem = (item: T) => {\n const exists = isSelected(item);\n const next = exists\n ? selectedValues.filter(\n (v) => getValue(v, optionValue) !== getValue(item, optionValue),\n )\n : [...selectedValues, item];\n\n const syntheticEvent = {\n target: { value: next },\n } as React.ChangeEvent<any>;\n\n onChange?.(syntheticEvent, next);\n };\n\n const removeItem = (item: T) => {\n const next = selectedValues.filter(\n (v) => getValue(v, optionValue) !== getValue(item, optionValue),\n );\n const syntheticEvent = {\n target: { value: next },\n } as React.ChangeEvent<any>;\n onChange?.(syntheticEvent, next);\n };\n\n const renderCheckbox = (checked: boolean) => (\n <View\n style={[\n styles.checkbox,\n { borderColor: colors.checkboxBorder, backgroundColor: colors.bg },\n checked && { backgroundColor: colors.checkboxChecked, borderColor: colors.checkboxChecked },\n ]}\n >\n {checked && <Text style={styles.checkmark}>✓</Text>}\n </View>\n );\n\n const renderListContent = () => {\n if (loading) {\n return (\n <View style={styles.loadingContainer}>\n <ActivityIndicator size=\"small\" color={colors.checkboxChecked} />\n <Text style={[styles.loadingText, { color: colors.placeholder }]}>Loading...</Text>\n </View>\n );\n }\n\n const itemsOnly = filtered.filter((e) => e.type === 'item');\n if (itemsOnly.length === 0) {\n return (\n <View style={styles.emptyContainer}>\n <Text style={[styles.emptyText, { color: colors.placeholder }]}>{emptyFilterMessage}</Text>\n </View>\n );\n }\n\n return (\n <FlatList\n data={filtered}\n keyExtractor={(entry, i) =>\n entry.type === 'group' ? `group-${i}` : `item-${i}`\n }\n keyboardShouldPersistTaps=\"handled\"\n renderItem={({ item: entry }) => {\n if (entry.type === 'group') {\n return (\n <View style={[styles.groupHeader, { backgroundColor: colors.groupBg, borderBottomColor: colors.groupBorder }]}>\n <Text style={[styles.groupHeaderText, { color: colors.textSecondary }]}>\n {getLabel(entry.data, optionGroupLabel)}\n </Text>\n </View>\n );\n }\n const checked = isSelected(entry.data);\n return (\n <TouchableOpacity\n onPress={() => toggleItem(entry.data)}\n style={[\n styles.item,\n { borderBottomColor: colors.itemBorder },\n checked && { backgroundColor: colors.itemSelectedBg },\n ]}\n activeOpacity={0.7}\n >\n {renderCheckbox(checked)}\n {itemTemplate ? (\n itemTemplate(entry.data)\n ) : (\n <Text style={[\n styles.itemText,\n { color: colors.text, fontFamily },\n checked && { color: colors.itemSelectedText, fontWeight: '500' },\n /* ⛔ The physical edge is COMPUTED — React Native mirrors\n `textAlign` when the process is RTL, so naming the RTL edge\n for an RTL reader lands on the LTR one. See `readerEdge`. */\n {\n textAlign: edge.textAlign,\n writingDirection: isRTL ? ('rtl' as const) : ('ltr' as const),\n },\n ]}>\n {getLabel(entry.data, optionLabel)}\n </Text>\n )}\n </TouchableOpacity>\n );\n }}\n />\n );\n };\n\n const renderSelected = () => {\n if (!selectedValues.length) {\n return <Text style={[styles.placeholder, { color: colors.placeholder }, externalTextStyle]}>{placeholder}</Text>;\n }\n\n if (display === 'chip') {\n const visibleItems = selectedValues.slice(0, maxSelectedLabels);\n const remaining = selectedValues.length - maxSelectedLabels;\n return (\n <View style={styles.chips}>\n {visibleItems.map((item, i) =>\n selectedItemTemplate ? (\n <React.Fragment key={i}>{selectedItemTemplate(item)}</React.Fragment>\n ) : (\n <View key={i} style={[styles.chip, { backgroundColor: colors.chipBg }]}>\n <Text style={[styles.chipText, { color: colors.chipText }]}>{getLabel(item, optionLabel)}</Text>\n <TouchableOpacity\n onPress={() => removeItem(item)}\n hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}\n >\n <Text style={[styles.chipRemove, { color: colors.chipRemove }]}>✕</Text>\n </TouchableOpacity>\n </View>\n ),\n )}\n {remaining > 0 && (\n <View style={[styles.chipMore, { backgroundColor: colors.chipMoreBg }]}>\n <Text style={[styles.chipMoreText, { color: colors.textSecondary }]}>+{remaining}</Text>\n </View>\n )}\n </View>\n );\n }\n\n return (\n <Text numberOfLines={1} style={[styles.commaText, { color: colors.text }, externalTextStyle]}>\n {selectedValues\n .slice(0, maxSelectedLabels)\n .map((v) => getLabel(v, optionLabel))\n .join(', ')}\n </Text>\n );\n };\n\n const usePopup = popup && typeof renderPopup === 'function';\n\n const panelContent = (\n <View style={{ flex: 1 }}>\n {/* Header */}\n <View style={[styles.panelHeader, { borderBottomColor: colors.headerBorder }]}>\n <Text style={[styles.panelHeaderText, { color: colors.textSecondary }]}>\n {selectedValues.length} item{selectedValues.length !== 1 ? 's' : ''} selected\n </Text>\n {/* In popup mode the sheet already draws a close control, and two ✕\n in one header is a question the reader should not have to answer.\n The count stays — it is information, not chrome. */}\n {!usePopup && (\n <TouchableOpacity onPress={() => setOpen(false)}>\n <Text style={[styles.panelCloseText, { color: colors.placeholder }]}>✕</Text>\n </TouchableOpacity>\n )}\n </View>\n\n {/* Search */}\n {filter && (\n <View style={[styles.searchContainer, { borderColor: colors.border, backgroundColor: colors.searchBg }]}>\n <Text style={styles.searchIcon}>🔍</Text>\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder={filterPlaceholder}\n style={[\n styles.searchInput,\n { color: colors.text, fontFamily },\n // The filter follows the reader's language, not the platform's\n // layout direction — same rule as the Dropdown's panel.\n isRTL ? styles.searchRtl : styles.searchLtr,\n ]}\n placeholderTextColor={colors.placeholder}\n />\n </View>\n )}\n\n {/* List */}\n {renderListContent()}\n </View>\n );\n\n return (\n <View style={{ width: '100%' }}>\n {/* Input trigger */}\n <TouchableOpacity\n ref={triggerRef as any}\n activeOpacity={0.8}\n disabled={disabled}\n onPress={toggleOpen}\n style={[\n styles.input,\n { borderColor: colors.border, backgroundColor: colors.bg },\n disabled && { backgroundColor: colors.disabledBg, opacity: 0.6 },\n open && { borderColor: colors.borderFocus },\n externalViewStyle,\n ]}\n >\n <View style={styles.inputContent}>\n {renderSelected()}\n </View>\n <Text style={[styles.dropdownArrow, { color: colors.placeholder }]}>{open ? '▲' : '▼'}</Text>\n </TouchableOpacity>\n\n {/* Popup — the container comes from the wrapper (this library's own\n Dialog in sheet position); `panelContent` is unchanged. */}\n {usePopup && renderPopup!({\n visible: open,\n onClose: () => setOpen(false),\n title: popupTitle,\n children: panelContent,\n })}\n\n {/* Modal mode */}\n {!usePopup && isModal && (\n <Modal visible={open} transparent animationType=\"fade\">\n <Pressable style={styles.overlay} onPress={() => setOpen(false)}>\n <View\n style={[styles.modalPanel, { backgroundColor: colors.bg }]}\n onStartShouldSetResponder={() => true}\n >\n {panelContent}\n </View>\n </Pressable>\n </Modal>\n )}\n\n {/* Inline mode — Modal-portal popover anchored to trigger */}\n {!usePopup && !isModal && (\n <Modal\n visible={open && !!triggerLayout}\n transparent\n animationType=\"none\"\n onRequestClose={close}\n >\n <Pressable style={styles.popoverOverlay} onPress={close}>\n {triggerLayout && (() => {\n const screen = Dimensions.get('window');\n const PANEL_MAX_HEIGHT = 320;\n const GAP = 4;\n const spaceBelow = screen.height - (triggerLayout.y + triggerLayout.height);\n const spaceAbove = triggerLayout.y;\n const openUp = spaceBelow < PANEL_MAX_HEIGHT && spaceAbove > spaceBelow;\n const maxHeight = Math.min(\n PANEL_MAX_HEIGHT,\n openUp ? spaceAbove - GAP : spaceBelow - GAP,\n );\n const top = openUp\n ? triggerLayout.y - maxHeight - GAP\n : triggerLayout.y + triggerLayout.height + GAP;\n\n return (\n <View\n style={[\n styles.popoverPanel,\n {\n top,\n left: triggerLayout.x,\n width: triggerLayout.width,\n maxHeight,\n borderColor: colors.border,\n backgroundColor: colors.bg,\n },\n ]}\n onStartShouldSetResponder={() => true}\n >\n {panelContent}\n </View>\n );\n })()}\n </Pressable>\n </Modal>\n )}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n // Input\n input: {\n minHeight: 42,\n borderWidth: 1,\n borderRadius: 6,\n paddingHorizontal: 10,\n paddingVertical: 6,\n flexDirection: 'row',\n alignItems: 'center',\n },\n inputContent: {\n flex: 1,\n },\n dropdownArrow: {\n fontSize: 10,\n marginLeft: 8,\n },\n\n // Placeholder\n placeholder: { fontSize: 14 },\n commaText: { fontSize: 14 },\n\n // Chips display\n chips: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 4,\n },\n chip: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 10,\n paddingRight: 6,\n paddingVertical: 3,\n borderRadius: 16,\n gap: 4,\n },\n chipText: {\n fontSize: 13,\n },\n chipRemove: {\n fontSize: 12,\n paddingHorizontal: 2,\n },\n chipMore: {\n paddingHorizontal: 10,\n paddingVertical: 3,\n borderRadius: 16,\n },\n chipMoreText: {\n fontSize: 13,\n },\n\n // Panel header\n panelHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n paddingHorizontal: 12,\n paddingVertical: 10,\n borderBottomWidth: 1,\n },\n panelHeaderText: {\n fontSize: 13,\n },\n panelCloseText: {\n fontSize: 18,\n fontWeight: '600',\n },\n\n // Search\n searchContainer: {\n flexDirection: 'row',\n alignItems: 'center',\n margin: 8,\n paddingHorizontal: 10,\n height: 36,\n borderWidth: 1,\n borderRadius: 6,\n },\n searchIcon: {\n fontSize: 14,\n marginRight: 6,\n },\n searchInput: {\n flex: 1,\n fontSize: 14,\n paddingVertical: 0,\n },\n searchLtr: {\n textAlign: 'left' as const,\n writingDirection: 'ltr' as const,\n },\n searchRtl: {\n textAlign: 'right' as const,\n writingDirection: 'rtl' as const,\n },\n\n // Group header\n groupHeader: {\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n groupHeaderText: {\n fontSize: 12,\n fontWeight: '700',\n textTransform: 'uppercase',\n letterSpacing: 0.5,\n },\n\n // Items\n item: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingVertical: 10,\n paddingHorizontal: 12,\n gap: 10,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n itemText: {\n fontSize: 14,\n /* The label takes the row's spare width so `textAlign` has somewhere to\n push to — a shrink-wrapped Text ignores it. Already here, which is why\n MultiSelect needs no extra entry; Dropdown's label style carries no flex\n and got `optionLabelFill`. */\n flex: 1,\n },\n\n // Checkbox\n checkbox: {\n width: 20,\n height: 20,\n borderWidth: 2,\n borderRadius: 4,\n justifyContent: 'center',\n alignItems: 'center',\n },\n checkmark: {\n color: '#fff',\n fontSize: 13,\n fontWeight: '700',\n },\n\n // Loading / Empty\n loadingContainer: {\n padding: 24,\n alignItems: 'center',\n gap: 8,\n },\n loadingText: {\n fontSize: 13,\n },\n emptyContainer: {\n padding: 24,\n alignItems: 'center',\n },\n emptyText: {\n fontSize: 14,\n },\n\n // Modal\n overlay: {\n flex: 1,\n backgroundColor: 'rgba(0,0,0,0.4)',\n justifyContent: 'center',\n },\n modalPanel: {\n margin: 24,\n maxHeight: '70%',\n borderRadius: 12,\n overflow: 'hidden',\n },\n\n // Popover (Modal-portal)\n popoverOverlay: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n popoverPanel: {\n position: 'absolute',\n borderWidth: 1,\n borderRadius: 6,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 8,\n },\n});\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../../../../../apps/mobile/src/Core/MultiSelect/index.tsx"],"sourcesContent":["import React, { useMemo, useRef, useState } from 'react';\nimport {\n View,\n Text,\n TouchableOpacity,\n Modal,\n FlatList,\n TextInput,\n StyleSheet,\n Pressable,\n ActivityIndicator,\n Dimensions,\n} from 'react-native';\nimport { readerEdge } from '../../Factory/helpers/readerEdge';\nimport { resolveThemeTokenForNative } from '../../Factory/helpers/style';\n\nexport type MultiSelectChangeEvent<T> = React.ChangeEvent<{\n value: T[];\n}>;\n\nexport interface MultiSelectProps<T> {\n value?: T[] | null;\n onChange?: (e: MultiSelectChangeEvent<T>, selectedItems: T[]) => void;\n isModal?: boolean;\n\n options?: T[];\n\n optionLabel?: keyof T | string;\n optionValue?: keyof T | string;\n\n optionGroupLabel?: keyof T | string;\n optionGroupChildren?: keyof T | string;\n\n placeholder?: string;\n disabled?: boolean;\n loading?: boolean;\n filter?: boolean;\n emptyFilterMessage?: string;\n /**\n * Placeholder for the panel's filter field, already written in the reader's\n * language by the KitsConcerto wrapper — this component lives in\n * `apps/mobile`, which `packages/ui` imports, so it cannot translate.\n */\n filterPlaceholder?: string;\n /** Reader's direction, from the wrapper's `useLanguage().isRTL`. */\n isRTL?: boolean;\n /**\n * Font family the app's theme names for body text, resolved by the wrapper.\n * React Native does not cascade fontFamily through Views, so each text sink\n * must set it — see the Dropdown's own note.\n */\n fontFamily?: string;\n /**\n * Open the options in a popup that owns the screen instead of a panel\n * anchored to the trigger. Default false — see the Dropdown's own `popup`\n * for why the anchor is the thing being escaped.\n */\n popup?: boolean;\n /**\n * Supplies the popup's container. Injected by the KitsConcerto wrapper: the\n * container is this library's `KitsDialogControlled`, which lives in\n * `packages/ui`, and `packages/ui` imports THIS file.\n */\n renderPopup?: (args: {\n visible: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n }) => React.ReactNode;\n /** Title for the popup header. */\n popupTitle?: React.ReactNode;\n\n display?: 'comma' | 'chip';\n maxSelectedLabels?: number;\n\n itemTemplate?: (item: T) => React.ReactElement;\n selectedItemTemplate?: (item: T) => React.ReactElement;\n style?: import('react-native').ViewStyle;\n\n /* ─── Chip slots ─────────────────────────────────────────────────────\n Same three props, same meaning, as `Core/AutoComplete` — so the two\n chip-bearing controls take their chip styling from one place in the\n theme instead of each hardcoding its own. */\n /** A single chip (the `View`): background, radius, padding, margin. */\n tokenStyle?: import('react-native').ViewStyle;\n /** The chip's label `Text`: color, fontSize, fontWeight, fontFamily. */\n tokenLabelStyle?: import('react-native').TextStyle;\n /** The chip's remove (✕) `Text`: color, fontSize. */\n tokenIconStyle?: import('react-native').TextStyle;\n}\n\nconst t = resolveThemeTokenForNative;\n\nconst TEXT_STYLE_KEYS = new Set([\n 'fontSize', 'fontFamily', 'fontWeight', 'fontStyle',\n 'color', 'letterSpacing', 'lineHeight', 'textAlign',\n 'textDecorationLine', 'textTransform',\n]);\n\nfunction splitStyle(combined?: any): { viewStyle?: any; textStyle?: any } {\n if (!combined) return {};\n const view: Record<string, any> = {};\n const text: Record<string, any> = {};\n for (const [k, v] of Object.entries(combined)) {\n if (TEXT_STYLE_KEYS.has(k)) text[k] = v;\n else view[k] = v;\n }\n return {\n viewStyle: Object.keys(view).length ? view : undefined,\n textStyle: Object.keys(text).length ? text : undefined,\n };\n}\n\nexport default function MultiSelect<T>(props: MultiSelectProps<T>) {\n const {\n value,\n onChange,\n options = [],\n optionLabel,\n optionValue,\n optionGroupLabel,\n optionGroupChildren,\n isModal = false,\n placeholder = 'Select',\n disabled,\n loading,\n filter,\n // ⚠️ English literals of last resort, not translations — the wrapper always\n // passes the reader's own sentence. These only apply when this component is\n // used directly from `apps/mobile`, so a panel can never render blank.\n emptyFilterMessage = 'No results found',\n filterPlaceholder = 'Search...',\n isRTL = false,\n fontFamily,\n popup = false,\n renderPopup,\n popupTitle,\n display = 'chip',\n maxSelectedLabels = 10,\n itemTemplate,\n selectedItemTemplate,\n style: externalStyle,\n tokenStyle,\n tokenLabelStyle,\n tokenIconStyle,\n } = props;\n\n /* Physical edges to write so content lands where the reader starts. */\n const edge = readerEdge(isRTL);\n\n const triggerRef = useRef<View>(null);\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [triggerLayout, setTriggerLayout] = useState<{\n x: number; y: number; width: number; height: number;\n } | null>(null);\n\n const close = () => setOpen(false);\n\n const toggleOpen = () => {\n if (disabled) return;\n if (open) {\n setOpen(false);\n return;\n }\n triggerRef.current?.measureInWindow((x, y, width, height) => {\n setTriggerLayout({ x, y, width, height });\n setOpen(true);\n });\n };\n\n const { viewStyle: externalViewStyle, textStyle: externalTextStyle } = splitStyle(externalStyle);\n\n const colors = {\n border: t('border') || t('gray.300'),\n borderFocus: t('primary'),\n bg: t('surface-card') || '#fff',\n disabledBg: t('surface-ground') || t('gray.100'),\n placeholder: t('text-secondary') || t('gray.400'),\n text: t('text') || t('gray.800'),\n textSecondary: t('text-secondary') || t('gray.500'),\n chipBg: t('primary.100') || t('indigo.100'),\n chipText: t('primary.700') || t('indigo.700'),\n chipRemove: t('primary.500') || t('indigo.500'),\n chipMoreBg: t('surface-ground') || t('gray.100'),\n headerBorder: t('border') || t('gray.200'),\n groupBg: t('surface-ground') || t('gray.50'),\n groupBorder: t('border') || t('gray.200'),\n itemBorder: t('surface-ground') || t('gray.100'),\n itemSelectedBg: t('highlight-bg') || t('indigo.50'),\n itemSelectedText: t('primary.700') || t('indigo.700'),\n checkboxBorder: t('border') || t('gray.300'),\n checkboxChecked: t('primary'),\n invalidBorder: t('danger') || t('red.500'),\n searchBg: t('surface-ground') || t('gray.50'),\n };\n\n const getValue = (item: T, key?: keyof T | string) =>\n key ? (item as any)[key] : item;\n\n const getLabel = (item: T, key?: keyof T | string) =>\n String(key ? (item as any)[key] : item);\n\n const selectedValues = Array.isArray(value) ? value : [];\n\n // Build display items: flat list with optional group headers\n const displayItems: { type: 'group' | 'item'; data: any }[] = useMemo(() => {\n if (optionGroupLabel && optionGroupChildren) {\n const result: { type: 'group' | 'item'; data: any }[] = [];\n options.forEach((group: any) => {\n result.push({ type: 'group', data: group });\n const children = group[optionGroupChildren] ?? [];\n children.forEach((child: any) => result.push({ type: 'item', data: child }));\n });\n return result;\n }\n return options.map((item) => ({ type: 'item' as const, data: item }));\n }, [options, optionGroupLabel, optionGroupChildren]);\n\n const filtered = useMemo(() => {\n if (!filter || !query) return displayItems;\n return displayItems.filter((entry) => {\n if (entry.type === 'group') return true; // keep group headers\n return getLabel(entry.data, optionLabel)\n .toLowerCase()\n .includes(query.toLowerCase());\n });\n }, [query, displayItems]);\n\n const isSelected = (item: T) =>\n selectedValues.some(\n (v) => getValue(v, optionValue) === getValue(item, optionValue),\n );\n\n const toggleItem = (item: T) => {\n const exists = isSelected(item);\n const next = exists\n ? selectedValues.filter(\n (v) => getValue(v, optionValue) !== getValue(item, optionValue),\n )\n : [...selectedValues, item];\n\n const syntheticEvent = {\n target: { value: next },\n } as React.ChangeEvent<any>;\n\n onChange?.(syntheticEvent, next);\n };\n\n const removeItem = (item: T) => {\n const next = selectedValues.filter(\n (v) => getValue(v, optionValue) !== getValue(item, optionValue),\n );\n const syntheticEvent = {\n target: { value: next },\n } as React.ChangeEvent<any>;\n onChange?.(syntheticEvent, next);\n };\n\n const renderCheckbox = (checked: boolean) => (\n <View\n style={[\n styles.checkbox,\n { borderColor: colors.checkboxBorder, backgroundColor: colors.bg },\n checked && { backgroundColor: colors.checkboxChecked, borderColor: colors.checkboxChecked },\n ]}\n >\n {checked && <Text style={styles.checkmark}>✓</Text>}\n </View>\n );\n\n const renderListContent = () => {\n if (loading) {\n return (\n <View style={styles.loadingContainer}>\n <ActivityIndicator size=\"small\" color={colors.checkboxChecked} />\n <Text style={[styles.loadingText, { color: colors.placeholder }]}>Loading...</Text>\n </View>\n );\n }\n\n const itemsOnly = filtered.filter((e) => e.type === 'item');\n if (itemsOnly.length === 0) {\n return (\n <View style={styles.emptyContainer}>\n <Text style={[styles.emptyText, { color: colors.placeholder }]}>{emptyFilterMessage}</Text>\n </View>\n );\n }\n\n return (\n <FlatList\n data={filtered}\n keyExtractor={(entry, i) =>\n entry.type === 'group' ? `group-${i}` : `item-${i}`\n }\n keyboardShouldPersistTaps=\"handled\"\n renderItem={({ item: entry }) => {\n if (entry.type === 'group') {\n return (\n <View style={[styles.groupHeader, { backgroundColor: colors.groupBg, borderBottomColor: colors.groupBorder }]}>\n <Text style={[styles.groupHeaderText, { color: colors.textSecondary }]}>\n {getLabel(entry.data, optionGroupLabel)}\n </Text>\n </View>\n );\n }\n const checked = isSelected(entry.data);\n return (\n <TouchableOpacity\n onPress={() => toggleItem(entry.data)}\n style={[\n styles.item,\n { borderBottomColor: colors.itemBorder },\n checked && { backgroundColor: colors.itemSelectedBg },\n ]}\n activeOpacity={0.7}\n >\n {renderCheckbox(checked)}\n {itemTemplate ? (\n itemTemplate(entry.data)\n ) : (\n <Text style={[\n styles.itemText,\n { color: colors.text, fontFamily },\n checked && { color: colors.itemSelectedText, fontWeight: '500' },\n /* ⛔ The physical edge is COMPUTED — React Native mirrors\n `textAlign` when the process is RTL, so naming the RTL edge\n for an RTL reader lands on the LTR one. See `readerEdge`. */\n {\n textAlign: edge.textAlign,\n writingDirection: isRTL ? ('rtl' as const) : ('ltr' as const),\n },\n ]}>\n {getLabel(entry.data, optionLabel)}\n </Text>\n )}\n </TouchableOpacity>\n );\n }}\n />\n );\n };\n\n const renderSelected = () => {\n if (!selectedValues.length) {\n return <Text style={[styles.placeholder, { color: colors.placeholder }, externalTextStyle]}>{placeholder}</Text>;\n }\n\n if (display === 'chip') {\n const visibleItems = selectedValues.slice(0, maxSelectedLabels);\n const remaining = selectedValues.length - maxSelectedLabels;\n return (\n <View style={styles.chips}>\n {visibleItems.map((item, i) =>\n selectedItemTemplate ? (\n <React.Fragment key={i}>{selectedItemTemplate(item)}</React.Fragment>\n ) : (\n <View key={i} style={[styles.chip, { backgroundColor: colors.chipBg }, tokenStyle]}>\n <Text style={[styles.chipText, { color: colors.chipText }, tokenLabelStyle]}>{getLabel(item, optionLabel)}</Text>\n <TouchableOpacity\n onPress={() => removeItem(item)}\n hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}\n >\n <Text style={[styles.chipRemove, { color: colors.chipRemove }, tokenIconStyle]}>✕</Text>\n </TouchableOpacity>\n </View>\n ),\n )}\n {remaining > 0 && (\n <View style={[styles.chipMore, { backgroundColor: colors.chipMoreBg }]}>\n <Text style={[styles.chipMoreText, { color: colors.textSecondary }]}>+{remaining}</Text>\n </View>\n )}\n </View>\n );\n }\n\n return (\n <Text numberOfLines={1} style={[styles.commaText, { color: colors.text }, externalTextStyle]}>\n {selectedValues\n .slice(0, maxSelectedLabels)\n .map((v) => getLabel(v, optionLabel))\n .join(', ')}\n </Text>\n );\n };\n\n const usePopup = popup && typeof renderPopup === 'function';\n\n const panelContent = (\n <View style={{ flex: 1 }}>\n {/* Header */}\n <View style={[styles.panelHeader, { borderBottomColor: colors.headerBorder }]}>\n <Text style={[styles.panelHeaderText, { color: colors.textSecondary }]}>\n {selectedValues.length} item{selectedValues.length !== 1 ? 's' : ''} selected\n </Text>\n {/* In popup mode the sheet already draws a close control, and two ✕\n in one header is a question the reader should not have to answer.\n The count stays — it is information, not chrome. */}\n {!usePopup && (\n <TouchableOpacity onPress={() => setOpen(false)}>\n <Text style={[styles.panelCloseText, { color: colors.placeholder }]}>✕</Text>\n </TouchableOpacity>\n )}\n </View>\n\n {/* Search */}\n {filter && (\n <View style={[styles.searchContainer, { borderColor: colors.border, backgroundColor: colors.searchBg }]}>\n <Text style={styles.searchIcon}>🔍</Text>\n <TextInput\n value={query}\n onChangeText={setQuery}\n placeholder={filterPlaceholder}\n style={[\n styles.searchInput,\n { color: colors.text, fontFamily },\n // The filter follows the reader's language, not the platform's\n // layout direction — same rule as the Dropdown's panel.\n isRTL ? styles.searchRtl : styles.searchLtr,\n ]}\n placeholderTextColor={colors.placeholder}\n />\n </View>\n )}\n\n {/* List */}\n {renderListContent()}\n </View>\n );\n\n return (\n <View style={{ width: '100%' }}>\n {/* Input trigger */}\n <TouchableOpacity\n ref={triggerRef as any}\n activeOpacity={0.8}\n disabled={disabled}\n onPress={toggleOpen}\n style={[\n styles.input,\n { borderColor: colors.border, backgroundColor: colors.bg },\n disabled && { backgroundColor: colors.disabledBg, opacity: 0.6 },\n open && { borderColor: colors.borderFocus },\n externalViewStyle,\n ]}\n >\n <View style={styles.inputContent}>\n {renderSelected()}\n </View>\n <Text style={[styles.dropdownArrow, { color: colors.placeholder }]}>{open ? '▲' : '▼'}</Text>\n </TouchableOpacity>\n\n {/* Popup — the container comes from the wrapper (this library's own\n Dialog in sheet position); `panelContent` is unchanged. */}\n {usePopup && renderPopup!({\n visible: open,\n onClose: () => setOpen(false),\n title: popupTitle,\n children: panelContent,\n })}\n\n {/* Modal mode */}\n {!usePopup && isModal && (\n <Modal visible={open} transparent animationType=\"fade\">\n <Pressable style={styles.overlay} onPress={() => setOpen(false)}>\n <View\n style={[styles.modalPanel, { backgroundColor: colors.bg }]}\n onStartShouldSetResponder={() => true}\n >\n {panelContent}\n </View>\n </Pressable>\n </Modal>\n )}\n\n {/* Inline mode — Modal-portal popover anchored to trigger */}\n {!usePopup && !isModal && (\n <Modal\n visible={open && !!triggerLayout}\n transparent\n animationType=\"none\"\n onRequestClose={close}\n >\n <Pressable style={styles.popoverOverlay} onPress={close}>\n {triggerLayout && (() => {\n const screen = Dimensions.get('window');\n const PANEL_MAX_HEIGHT = 320;\n const GAP = 4;\n const spaceBelow = screen.height - (triggerLayout.y + triggerLayout.height);\n const spaceAbove = triggerLayout.y;\n const openUp = spaceBelow < PANEL_MAX_HEIGHT && spaceAbove > spaceBelow;\n const maxHeight = Math.min(\n PANEL_MAX_HEIGHT,\n openUp ? spaceAbove - GAP : spaceBelow - GAP,\n );\n const top = openUp\n ? triggerLayout.y - maxHeight - GAP\n : triggerLayout.y + triggerLayout.height + GAP;\n\n return (\n <View\n style={[\n styles.popoverPanel,\n {\n top,\n left: triggerLayout.x,\n width: triggerLayout.width,\n maxHeight,\n borderColor: colors.border,\n backgroundColor: colors.bg,\n },\n ]}\n onStartShouldSetResponder={() => true}\n >\n {panelContent}\n </View>\n );\n })()}\n </Pressable>\n </Modal>\n )}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n // Input\n input: {\n minHeight: 42,\n borderWidth: 1,\n borderRadius: 6,\n paddingHorizontal: 10,\n paddingVertical: 6,\n flexDirection: 'row',\n alignItems: 'center',\n },\n inputContent: {\n flex: 1,\n },\n dropdownArrow: {\n fontSize: 10,\n marginLeft: 8,\n },\n\n // Placeholder\n placeholder: { fontSize: 14 },\n commaText: { fontSize: 14 },\n\n // Chips display\n chips: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n gap: 4,\n },\n chip: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingLeft: 10,\n paddingRight: 6,\n paddingVertical: 3,\n borderRadius: 16,\n gap: 4,\n },\n chipText: {\n fontSize: 13,\n },\n chipRemove: {\n fontSize: 12,\n paddingHorizontal: 2,\n },\n chipMore: {\n paddingHorizontal: 10,\n paddingVertical: 3,\n borderRadius: 16,\n },\n chipMoreText: {\n fontSize: 13,\n },\n\n // Panel header\n panelHeader: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n paddingHorizontal: 12,\n paddingVertical: 10,\n borderBottomWidth: 1,\n },\n panelHeaderText: {\n fontSize: 13,\n },\n panelCloseText: {\n fontSize: 18,\n fontWeight: '600',\n },\n\n // Search\n searchContainer: {\n flexDirection: 'row',\n alignItems: 'center',\n margin: 8,\n paddingHorizontal: 10,\n height: 36,\n borderWidth: 1,\n borderRadius: 6,\n },\n searchIcon: {\n fontSize: 14,\n marginRight: 6,\n },\n searchInput: {\n flex: 1,\n fontSize: 14,\n paddingVertical: 0,\n },\n searchLtr: {\n textAlign: 'left' as const,\n writingDirection: 'ltr' as const,\n },\n searchRtl: {\n textAlign: 'right' as const,\n writingDirection: 'rtl' as const,\n },\n\n // Group header\n groupHeader: {\n paddingHorizontal: 12,\n paddingVertical: 8,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n groupHeaderText: {\n fontSize: 12,\n fontWeight: '700',\n textTransform: 'uppercase',\n letterSpacing: 0.5,\n },\n\n // Items\n item: {\n flexDirection: 'row',\n alignItems: 'center',\n paddingVertical: 10,\n paddingHorizontal: 12,\n gap: 10,\n borderBottomWidth: StyleSheet.hairlineWidth,\n },\n itemText: {\n fontSize: 14,\n /* The label takes the row's spare width so `textAlign` has somewhere to\n push to — a shrink-wrapped Text ignores it. Already here, which is why\n MultiSelect needs no extra entry; Dropdown's label style carries no flex\n and got `optionLabelFill`. */\n flex: 1,\n },\n\n // Checkbox\n checkbox: {\n width: 20,\n height: 20,\n borderWidth: 2,\n borderRadius: 4,\n justifyContent: 'center',\n alignItems: 'center',\n },\n checkmark: {\n color: '#fff',\n fontSize: 13,\n fontWeight: '700',\n },\n\n // Loading / Empty\n loadingContainer: {\n padding: 24,\n alignItems: 'center',\n gap: 8,\n },\n loadingText: {\n fontSize: 13,\n },\n emptyContainer: {\n padding: 24,\n alignItems: 'center',\n },\n emptyText: {\n fontSize: 14,\n },\n\n // Modal\n overlay: {\n flex: 1,\n backgroundColor: 'rgba(0,0,0,0.4)',\n justifyContent: 'center',\n },\n modalPanel: {\n margin: 24,\n maxHeight: '70%',\n borderRadius: 12,\n overflow: 'hidden',\n },\n\n // Popover (Modal-portal)\n popoverOverlay: {\n flex: 1,\n backgroundColor: 'transparent',\n },\n popoverPanel: {\n position: 'absolute',\n borderWidth: 1,\n borderRadius: 6,\n overflow: 'hidden',\n elevation: 8,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 2 },\n shadowOpacity: 0.15,\n shadowRadius: 8,\n },\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":"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"}
|
|
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":"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"}
|
|
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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
|
);
|