@lmb-it/kitsconcerto-native 0.1.273 → 0.1.275
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Avatar/index.cjs +1 -0
- package/components/Avatar/index.cjs.map +1 -1
- package/components/Avatar/index.js +1 -0
- package/components/Avatar/index.js.map +1 -1
- package/components/Banner/banner.cjs +1 -0
- package/components/Banner/banner.cjs.map +1 -1
- package/components/Banner/banner.js +1 -0
- package/components/Banner/banner.js.map +1 -1
- package/components/BottomTabBar/index.cjs +1 -0
- package/components/BottomTabBar/index.cjs.map +1 -1
- package/components/BottomTabBar/index.js +1 -0
- package/components/BottomTabBar/index.js.map +1 -1
- package/components/Button/Button.cjs +1 -0
- package/components/Button/Button.cjs.map +1 -1
- package/components/Button/Button.js +1 -0
- package/components/Button/Button.js.map +1 -1
- package/components/Carousel/index.cjs +1 -0
- package/components/Carousel/index.cjs.map +1 -1
- package/components/Carousel/index.js +1 -0
- package/components/Carousel/index.js.map +1 -1
- package/components/ChatBubble/index.cjs +1 -0
- package/components/ChatBubble/index.cjs.map +1 -1
- package/components/ChatBubble/index.js +1 -0
- package/components/ChatBubble/index.js.map +1 -1
- package/components/Chip/index.cjs +1 -0
- package/components/Chip/index.cjs.map +1 -1
- package/components/Chip/index.js +1 -0
- package/components/Chip/index.js.map +1 -1
- package/components/DateSeparator/index.cjs +1 -0
- package/components/DateSeparator/index.cjs.map +1 -1
- package/components/DateSeparator/index.js +1 -0
- package/components/DateSeparator/index.js.map +1 -1
- package/components/DetailsList/index.cjs +1 -0
- package/components/DetailsList/index.cjs.map +1 -1
- package/components/DetailsList/index.js +1 -0
- package/components/DetailsList/index.js.map +1 -1
- package/components/EmptyState/index.cjs +1 -0
- package/components/EmptyState/index.cjs.map +1 -1
- package/components/EmptyState/index.js +1 -0
- package/components/EmptyState/index.js.map +1 -1
- package/components/Gallery/index.cjs +1 -0
- package/components/Gallery/index.cjs.map +1 -1
- package/components/Gallery/index.js +1 -0
- package/components/Gallery/index.js.map +1 -1
- package/components/MessageComposer/index.cjs +1 -0
- package/components/MessageComposer/index.cjs.map +1 -1
- package/components/MessageComposer/index.js +1 -0
- package/components/MessageComposer/index.js.map +1 -1
- package/components/MessageReceipt/index.cjs +1 -0
- package/components/MessageReceipt/index.cjs.map +1 -1
- package/components/MessageReceipt/index.js +1 -0
- package/components/MessageReceipt/index.js.map +1 -1
- package/components/ProgressBar/index.cjs +1 -0
- package/components/ProgressBar/index.cjs.map +1 -1
- package/components/ProgressBar/index.js +1 -0
- package/components/ProgressBar/index.js.map +1 -1
- package/components/SegmentedControl/index.cjs +1 -0
- package/components/SegmentedControl/index.cjs.map +1 -1
- package/components/SegmentedControl/index.js +1 -0
- package/components/SegmentedControl/index.js.map +1 -1
- package/components/StatCard/index.cjs +1 -0
- package/components/StatCard/index.cjs.map +1 -1
- package/components/StatCard/index.js +1 -0
- package/components/StatCard/index.js.map +1 -1
- package/components/Stepper/index.cjs +1 -0
- package/components/Stepper/index.cjs.map +1 -1
- package/components/Stepper/index.js +1 -0
- package/components/Stepper/index.js.map +1 -1
- package/components/Tabs/index.cjs +1 -0
- package/components/Tabs/index.cjs.map +1 -1
- package/components/Tabs/index.js +1 -0
- package/components/Tabs/index.js.map +1 -1
- package/components/Timeline/index.cjs +1 -0
- package/components/Timeline/index.cjs.map +1 -1
- package/components/Timeline/index.js +1 -0
- package/components/Timeline/index.js.map +1 -1
- package/components/Translate/index.cjs +1 -0
- package/components/Translate/index.cjs.map +1 -1
- package/components/Translate/index.js +1 -0
- package/components/Translate/index.js.map +1 -1
- package/components/TypingIndicator/index.cjs +1 -0
- package/components/TypingIndicator/index.cjs.map +1 -1
- package/components/TypingIndicator/index.js +1 -0
- package/components/TypingIndicator/index.js.map +1 -1
- package/components/overlay/ConfirmDialog/index.cjs +1 -0
- package/components/overlay/ConfirmDialog/index.cjs.map +1 -1
- package/components/overlay/ConfirmDialog/index.js +1 -0
- package/components/overlay/ConfirmDialog/index.js.map +1 -1
- package/components/overlay/Dialog/index.cjs +1 -0
- package/components/overlay/Dialog/index.cjs.map +1 -1
- package/components/overlay/Dialog/index.js +1 -0
- package/components/overlay/Dialog/index.js.map +1 -1
- package/contexts/PermissionsContext.cjs +2 -0
- package/contexts/PermissionsContext.cjs.map +1 -1
- package/contexts/PermissionsContext.js +3 -2
- package/contexts/PermissionsContext.js.map +1 -1
- package/form/controls/Checkbox/index.cjs +1 -0
- package/form/controls/Checkbox/index.cjs.map +1 -1
- package/form/controls/Checkbox/index.js +1 -0
- package/form/controls/Checkbox/index.js.map +1 -1
- package/form/controls/RadioButton/radio.cjs +1 -0
- package/form/controls/RadioButton/radio.cjs.map +1 -1
- package/form/controls/RadioButton/radio.js +1 -0
- package/form/controls/RadioButton/radio.js.map +1 -1
- package/form/controls/TriStateCheckbox/index.cjs +1 -0
- package/form/controls/TriStateCheckbox/index.cjs.map +1 -1
- package/form/controls/TriStateCheckbox/index.js +1 -0
- package/form/controls/TriStateCheckbox/index.js.map +1 -1
- package/form/file-pickers/index.cjs +1 -0
- package/form/file-pickers/index.cjs.map +1 -1
- package/form/file-pickers/index.js +1 -0
- package/form/file-pickers/index.js.map +1 -1
- package/form/helpers/FormContainer/index.cjs +1 -0
- package/form/helpers/FormContainer/index.cjs.map +1 -1
- package/form/helpers/FormContainer/index.js +1 -0
- package/form/helpers/FormContainer/index.js.map +1 -1
- package/form/inputs/ColorPicker/index.cjs +1 -0
- package/form/inputs/ColorPicker/index.cjs.map +1 -1
- package/form/inputs/ColorPicker/index.js +1 -0
- package/form/inputs/ColorPicker/index.js.map +1 -1
- package/form/inputs/Datepicker/index.cjs +1 -0
- package/form/inputs/Datepicker/index.cjs.map +1 -1
- package/form/inputs/Datepicker/index.js +1 -0
- package/form/inputs/Datepicker/index.js.map +1 -1
- package/form/inputs/InputLocation/index.cjs +1 -0
- package/form/inputs/InputLocation/index.cjs.map +1 -1
- package/form/inputs/InputLocation/index.js +1 -0
- package/form/inputs/InputLocation/index.js.map +1 -1
- package/form/inputs/InputMask/index.cjs +1 -0
- package/form/inputs/InputMask/index.cjs.map +1 -1
- package/form/inputs/InputMask/index.js +1 -0
- package/form/inputs/InputMask/index.js.map +1 -1
- package/form/inputs/InputNumber/index.cjs +1 -0
- package/form/inputs/InputNumber/index.cjs.map +1 -1
- package/form/inputs/InputNumber/index.js +1 -0
- package/form/inputs/InputNumber/index.js.map +1 -1
- package/form/inputs/InputPassword/index.cjs +1 -0
- package/form/inputs/InputPassword/index.cjs.map +1 -1
- package/form/inputs/InputPassword/index.js +1 -0
- package/form/inputs/InputPassword/index.js.map +1 -1
- package/form/inputs/InputSwitch/index.cjs +1 -0
- package/form/inputs/InputSwitch/index.cjs.map +1 -1
- package/form/inputs/InputSwitch/index.js +1 -0
- package/form/inputs/InputSwitch/index.js.map +1 -1
- package/form/inputs/InputText/index.cjs +1 -0
- package/form/inputs/InputText/index.cjs.map +1 -1
- package/form/inputs/InputText/index.js +1 -0
- package/form/inputs/InputText/index.js.map +1 -1
- package/form/inputs/InputTextarea/index.cjs +1 -0
- package/form/inputs/InputTextarea/index.cjs.map +1 -1
- package/form/inputs/InputTextarea/index.js +1 -0
- package/form/inputs/InputTextarea/index.js.map +1 -1
- package/form/inputs/PhoneInput/index.cjs +1 -0
- package/form/inputs/PhoneInput/index.cjs.map +1 -1
- package/form/inputs/PhoneInput/index.js +1 -0
- package/form/inputs/PhoneInput/index.js.map +1 -1
- package/form/selects/AutoComplete/index.cjs +1 -0
- package/form/selects/AutoComplete/index.cjs.map +1 -1
- package/form/selects/AutoComplete/index.js +1 -0
- package/form/selects/AutoComplete/index.js.map +1 -1
- package/form/selects/CascadeSelect/index.cjs +1 -0
- package/form/selects/CascadeSelect/index.cjs.map +1 -1
- package/form/selects/CascadeSelect/index.js +1 -0
- package/form/selects/CascadeSelect/index.js.map +1 -1
- package/form/selects/Dropdown/index.cjs +1 -0
- package/form/selects/Dropdown/index.cjs.map +1 -1
- package/form/selects/Dropdown/index.js +1 -0
- package/form/selects/Dropdown/index.js.map +1 -1
- package/form/selects/ListBox/index.cjs +1 -0
- package/form/selects/ListBox/index.cjs.map +1 -1
- package/form/selects/ListBox/index.js +1 -0
- package/form/selects/ListBox/index.js.map +1 -1
- package/form/selects/MultiSelect/index.cjs +1 -0
- package/form/selects/MultiSelect/index.cjs.map +1 -1
- package/form/selects/MultiSelect/index.js +1 -0
- package/form/selects/MultiSelect/index.js.map +1 -1
- package/form/selects/TreeSelect/index.cjs +1 -0
- package/form/selects/TreeSelect/index.cjs.map +1 -1
- package/form/selects/TreeSelect/index.js +1 -0
- package/form/selects/TreeSelect/index.js.map +1 -1
- package/form/selects/helpers/SelectPopupOverlay.cjs +1 -0
- package/form/selects/helpers/SelectPopupOverlay.cjs.map +1 -1
- package/form/selects/helpers/SelectPopupOverlay.js +1 -0
- package/form/selects/helpers/SelectPopupOverlay.js.map +1 -1
- package/form-renderer/components/fields/FileUploader/index.cjs +1 -0
- package/form-renderer/components/fields/FileUploader/index.cjs.map +1 -1
- package/form-renderer/components/fields/FileUploader/index.js +1 -0
- package/form-renderer/components/fields/FileUploader/index.js.map +1 -1
- package/form-renderer/components/fields/Group/index.cjs +1 -0
- package/form-renderer/components/fields/Group/index.cjs.map +1 -1
- package/form-renderer/components/fields/Group/index.js +1 -0
- package/form-renderer/components/fields/Group/index.js.map +1 -1
- package/form-renderer/components/fields/Radios/index.cjs +1 -0
- package/form-renderer/components/fields/Radios/index.cjs.map +1 -1
- package/form-renderer/components/fields/Radios/index.js +1 -0
- package/form-renderer/components/fields/Radios/index.js.map +1 -1
- package/form-renderer/components/fields/Select/index.cjs +1 -0
- package/form-renderer/components/fields/Select/index.cjs.map +1 -1
- package/form-renderer/components/fields/Select/index.js +1 -0
- package/form-renderer/components/fields/Select/index.js.map +1 -1
- package/hooks/main.cjs +1 -0
- package/hooks/main.cjs.map +1 -1
- package/hooks/main.js +1 -0
- package/hooks/main.js.map +1 -1
- package/index.cjs +3 -0
- package/index.cjs.map +1 -1
- package/index.d.ts +10 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/primitives/Card/index.cjs +1 -0
- package/primitives/Card/index.cjs.map +1 -1
- package/primitives/Card/index.js +1 -0
- package/primitives/Card/index.js.map +1 -1
|
@@ -7,6 +7,7 @@ var index_native$1 = require('../../primitives/Image/index.cjs');
|
|
|
7
7
|
var index_native = require('../../primitives/Icon/index.cjs');
|
|
8
8
|
require('react');
|
|
9
9
|
require('../../contexts/DialogContext.cjs');
|
|
10
|
+
require('../../contexts/PermissionsContext.cjs');
|
|
10
11
|
var useComponentDefaults = require('../../hooks/useComponentDefaults.cjs');
|
|
11
12
|
|
|
12
13
|
const SIZE_PX = { xs: 24, sm: 32, md: 40, lg: 56, xl: 72 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from \"react\";\nimport type {IAvatarProps, IAvatarStackProps, AvatarSize} from \"@lmb-it/kitsconcerto-types\";\nimport {Box, Text, Image, Icon} from \"../../primitives\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n/* ─── Size resolution ─────────────────────────────────────────── */\nconst SIZE_PX: Record<string, number> = {xs: 24, sm: 32, md: 40, lg: 56, xl: 72};\n\nfunction resolveSize(size: AvatarSize | undefined): number {\n if (typeof size === \"number\") return size;\n return SIZE_PX[size ?? \"md\"] ?? 40;\n}\n\n/* ─── Status dot → semantic token ─────────────────────────────── */\nconst STATUS_TOKENS: Record<string, string> = {\n online: \"success\",\n offline: \"gray.400\",\n away: \"warning\",\n busy: \"danger\",\n};\n\n/* ─── Deterministic monogram palette (all confirmed theme tokens) ─ */\nconst MONOGRAM_PALETTE = [\"brand\", \"primary.800\", \"success\", \"danger\", \"ink.700\"];\n\nfunction hashIndex(input: string, mod: number): number {\n let h = 0;\n for (let i = 0; i < input.length; i++) h = (h * 31 + input.charCodeAt(i)) >>> 0;\n return mod > 0 ? h % mod : 0;\n}\n\nfunction deriveInitials(name?: string, initials?: string): string {\n if (initials) return initials.slice(0, 3).toUpperCase();\n if (!name) return \"\";\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"\";\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return (parts[0]!.charAt(0) + parts[parts.length - 1]!.charAt(0)).toUpperCase();\n}\n\n/**\n * Avatar — image / monogram / icon identity tile.\n *\n * Pure presentational and cross-platform: composed from the `Box` + `Text` +\n * `Image` + `Icon` primitives, so it renders identically on web and native\n * with no platform split. Tappability is the caller's concern (wrap in a\n * Pressable / Button).\n *\n * <Avatar src=\"https://…/me.jpg\" size=\"lg\" />\n * <Avatar name=\"Fouad K\" status=\"online\" />\n * <Avatar initials=\"C\" masked /> // identity-masked (Flex)\n * <Avatar name=\"Acme\" shape=\"rounded\" badge={<Icon name=\"briefcase\" />} />\n */\nexport function Avatar(props: IAvatarProps) {\n const {mergedProps} = useComponentDefaults<IAvatarProps>(\"Avatar\", props);\n const {\n src,\n name,\n initials,\n icon,\n size = \"md\",\n shape = \"circle\",\n color,\n status = \"none\",\n ring = false,\n ringColor = \"brand\",\n masked = false,\n maskFillColor = \"indigo.600\",\n badge,\n alt,\n testID,\n ...rest\n } = mergedProps;\n\n const px = resolveSize(size);\n const radius = shape === \"circle\" ? px / 2 : Math.round(px * 0.28);\n const fontSize = Math.max(10, Math.round(px * 0.4));\n const iconSize = Math.round(px * 0.5);\n const dot = Math.max(8, Math.round(px * 0.28));\n const ringW = px >= 56 ? 3 : 2;\n\n const resolvedInitials = deriveInitials(name, initials);\n const hasImage = !!src;\n const showInitials = !hasImage && resolvedInitials.length > 0;\n const showIcon = !hasImage && !showInitials && icon != null;\n\n const monogramBg =\n color ?? (MONOGRAM_PALETTE[hashIndex(name ?? resolvedInitials, MONOGRAM_PALETTE.length)] ?? \"brand\");\n const surfaceBg = masked ? maskFillColor : hasImage ? \"gray.100\" : monogramBg;\n const initialsColor = \"#FFFFFF\";\n\n const statusColor = STATUS_TOKENS[status] ?? \"gray.400\";\n const ariaLabel = alt ?? name ?? \"avatar\";\n\n const a11yProps = {\n role: \"img\",\n \"aria-label\": ariaLabel,\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box\n position=\"relative\"\n width={px}\n height={px}\n {...rest}\n {...(a11yProps as any)}\n >\n {/* Surface (clips the image / centres the monogram).\n overflow:hidden only when an image is present — clipping the\n monogram <Text> cuts off the glyph tops on native. */}\n <Box\n width=\"100%\"\n height=\"100%\"\n borderRadius={radius}\n overflow={hasImage && !masked ? \"hidden\" : \"visible\"}\n alignItems=\"center\"\n justifyContent=\"center\"\n bgColor={surfaceBg}\n >\n {masked ? (\n <Icon name=\"user\" size={iconSize} color=\"#FFFFFF\" />\n ) : hasImage ? (\n /*\n * width/height via style: the Image primitive types dimensions\n * differently per platform (web string vs native number).\n *\n * ⛔ `alt` IS REQUIRED HERE AND WAS MISSING — every Avatar with\n * a `src` warned, on every render. gluestack's own image creator\n * does `if (typeof alt !== 'string') console.warn('Please pass\n * alt prop to Image component')`, so the check is on the TYPE,\n * not on emptiness: a missing prop warns and an empty string\n * does not. Measured in AlphaMatch on 5 October 2026 — 21\n * warnings in a single sign-in from `AMTabBar`'s Me slot alone,\n * which is one Avatar.\n *\n * ⛔ AND IT IS EMPTY ON PURPOSE, NOT `ariaLabel`. The Box above\n * already carries `role=\"img\"` and `aria-label={ariaLabel}`, so\n * this image is PRESENTATION inside an element that is already\n * named; repeating the label here would announce the person's\n * name twice. Empty is the standing answer for a decorative\n * image, and it is this library's own: `PhoneInput` passes\n * `alt={countryISO ?? \"\"}` for exactly this reason.\n *\n * ⛔ `aria-hidden` IS THE OTHER HALF, AND `alt=\"\"` ALONE WAS NOT\n * ENOUGH — found by Codex, 5 October 2026. gluestack does not\n * only read `alt`; it also forces\n * `role={props.role || 'img'}`, so an empty alt leaves a\n * SECOND, NAMELESS image role sitting under the labelled Box.\n * On the web an `<img alt=\"\">` is decorative and harmless; on\n * React Native that role becomes `accessibilityRole=\"image\"`\n * and a screen reader can land on an unnamed image. Hiding the\n * node is what makes it presentational on both platforms —\n * RN maps `aria-hidden` to `accessibilityElementsHidden` on\n * iOS and `importantForAccessibility=\"no-hide-descendants\"` on\n * Android. `alt=\"\"` stays because it is what silences the\n * warning: gluestack checks `typeof alt !== 'string'`.\n *\n * ⚠️ `Gallery` HAS THE SAME MISSING `alt`, one file away, and is\n * NOT fixed here — it was outside what this change was opened\n * for. Recorded in the session report rather than swept in.\n */\n <Image\n src={src}\n alt=\"\"\n aria-hidden\n style={{width: px, height: px} as any}\n objectFit=\"cover\"\n />\n ) : showInitials ? (\n <Text\n color={initialsColor}\n fontSize={fontSize}\n fontWeight=\"700\"\n lineHeight={Math.round(fontSize * 1.2)}\n textAlign=\"center\"\n >\n {resolvedInitials}\n </Text>\n ) : showIcon ? (\n <Icon name={icon as never} size={iconSize} color=\"gray.500\" />\n ) : null}\n </Box>\n\n {/* Ring overlay (solid active ring) */}\n {ring && (\n <Box\n position=\"absolute\"\n top={0}\n right={0}\n bottom={0}\n left={0}\n borderRadius={radius}\n borderWidth={ringW}\n borderStyle=\"solid\"\n borderColor={ringColor}\n />\n )}\n\n {/* Badge OR presence dot (badge wins the corner) */}\n {badge != null ? (\n <Box position=\"absolute\" bottom={-2} right={-2} zIndex={2}>\n {badge}\n </Box>\n ) : status !== \"none\" ? (\n <Box\n position=\"absolute\"\n bottom={0}\n right={0}\n zIndex={2}\n width={dot}\n height={dot}\n borderRadius={dot}\n bgColor={statusColor}\n borderWidth={2}\n borderColor=\"surface-card\"\n />\n ) : null}\n </Box>\n );\n}\n\n/**\n * AvatarStack — overlapping row of avatars with a \"+N\" overflow tile.\n * Each avatar gets a surface-coloured cut-out ring so it reads cleanly\n * against the one behind it.\n *\n * <AvatarStack items={members} max={4} activeIndex={0} />\n */\nexport function AvatarStack(props: IAvatarStackProps) {\n const {mergedProps} = useComponentDefaults<IAvatarStackProps>(\"AvatarStack\", props);\n const {items, max = 4, size = \"md\", overlap = 0.35, activeIndex, ringColor = \"brand\", testID, ...rest} = mergedProps;\n\n const px = resolveSize(size);\n const clampedOverlap = Math.min(Math.max(overlap, 0), 0.9);\n const overlapPx = Math.round(px * clampedOverlap);\n const strokeW = px >= 56 ? 3 : 2;\n\n const visible = items.slice(0, max);\n const overflow = items.length - visible.length;\n\n const cell = (key: string, node: React.ReactNode, i: number) => (\n <Box\n key={key}\n marginLeft={i === 0 ? 0 : -overlapPx}\n zIndex={items.length - i}\n borderRadius={9999}\n borderWidth={strokeW}\n borderColor=\"surface-card\"\n bgColor=\"surface-card\"\n >\n {node}\n </Box>\n );\n\n const a11yProps = {\n role: \"group\",\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box flexDirection=\"row\" alignItems=\"center\" {...rest} {...(a11yProps as any)}>\n {visible.map((item, i) =>\n cell(\n `avatar-${i}`,\n <Avatar\n {...item}\n size={size}\n ring={i === activeIndex || item.ring}\n ringColor={item.ringColor ?? ringColor}\n />,\n i,\n ),\n )}\n {overflow > 0 && cell(\"avatar-overflow\", <Avatar initials={`+${overflow}`} size={size} color=\"ink.400\" />, visible.length)}\n </Box>\n );\n}\n\nexport default Avatar;\n"],"names":["useComponentDefaults","jsxs","Box","jsx","Icon","Image","Text"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from \"react\";\nimport type {IAvatarProps, IAvatarStackProps, AvatarSize} from \"@lmb-it/kitsconcerto-types\";\nimport {Box, Text, Image, Icon} from \"../../primitives\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n/* ─── Size resolution ─────────────────────────────────────────── */\nconst SIZE_PX: Record<string, number> = {xs: 24, sm: 32, md: 40, lg: 56, xl: 72};\n\nfunction resolveSize(size: AvatarSize | undefined): number {\n if (typeof size === \"number\") return size;\n return SIZE_PX[size ?? \"md\"] ?? 40;\n}\n\n/* ─── Status dot → semantic token ─────────────────────────────── */\nconst STATUS_TOKENS: Record<string, string> = {\n online: \"success\",\n offline: \"gray.400\",\n away: \"warning\",\n busy: \"danger\",\n};\n\n/* ─── Deterministic monogram palette (all confirmed theme tokens) ─ */\nconst MONOGRAM_PALETTE = [\"brand\", \"primary.800\", \"success\", \"danger\", \"ink.700\"];\n\nfunction hashIndex(input: string, mod: number): number {\n let h = 0;\n for (let i = 0; i < input.length; i++) h = (h * 31 + input.charCodeAt(i)) >>> 0;\n return mod > 0 ? h % mod : 0;\n}\n\nfunction deriveInitials(name?: string, initials?: string): string {\n if (initials) return initials.slice(0, 3).toUpperCase();\n if (!name) return \"\";\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"\";\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return (parts[0]!.charAt(0) + parts[parts.length - 1]!.charAt(0)).toUpperCase();\n}\n\n/**\n * Avatar — image / monogram / icon identity tile.\n *\n * Pure presentational and cross-platform: composed from the `Box` + `Text` +\n * `Image` + `Icon` primitives, so it renders identically on web and native\n * with no platform split. Tappability is the caller's concern (wrap in a\n * Pressable / Button).\n *\n * <Avatar src=\"https://…/me.jpg\" size=\"lg\" />\n * <Avatar name=\"Fouad K\" status=\"online\" />\n * <Avatar initials=\"C\" masked /> // identity-masked (Flex)\n * <Avatar name=\"Acme\" shape=\"rounded\" badge={<Icon name=\"briefcase\" />} />\n */\nexport function Avatar(props: IAvatarProps) {\n const {mergedProps} = useComponentDefaults<IAvatarProps>(\"Avatar\", props);\n const {\n src,\n name,\n initials,\n icon,\n size = \"md\",\n shape = \"circle\",\n color,\n status = \"none\",\n ring = false,\n ringColor = \"brand\",\n masked = false,\n maskFillColor = \"indigo.600\",\n badge,\n alt,\n testID,\n ...rest\n } = mergedProps;\n\n const px = resolveSize(size);\n const radius = shape === \"circle\" ? px / 2 : Math.round(px * 0.28);\n const fontSize = Math.max(10, Math.round(px * 0.4));\n const iconSize = Math.round(px * 0.5);\n const dot = Math.max(8, Math.round(px * 0.28));\n const ringW = px >= 56 ? 3 : 2;\n\n const resolvedInitials = deriveInitials(name, initials);\n const hasImage = !!src;\n const showInitials = !hasImage && resolvedInitials.length > 0;\n const showIcon = !hasImage && !showInitials && icon != null;\n\n const monogramBg =\n color ?? (MONOGRAM_PALETTE[hashIndex(name ?? resolvedInitials, MONOGRAM_PALETTE.length)] ?? \"brand\");\n const surfaceBg = masked ? maskFillColor : hasImage ? \"gray.100\" : monogramBg;\n const initialsColor = \"#FFFFFF\";\n\n const statusColor = STATUS_TOKENS[status] ?? \"gray.400\";\n const ariaLabel = alt ?? name ?? \"avatar\";\n\n const a11yProps = {\n role: \"img\",\n \"aria-label\": ariaLabel,\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box\n position=\"relative\"\n width={px}\n height={px}\n {...rest}\n {...(a11yProps as any)}\n >\n {/* Surface (clips the image / centres the monogram).\n overflow:hidden only when an image is present — clipping the\n monogram <Text> cuts off the glyph tops on native. */}\n <Box\n width=\"100%\"\n height=\"100%\"\n borderRadius={radius}\n overflow={hasImage && !masked ? \"hidden\" : \"visible\"}\n alignItems=\"center\"\n justifyContent=\"center\"\n bgColor={surfaceBg}\n >\n {masked ? (\n <Icon name=\"user\" size={iconSize} color=\"#FFFFFF\" />\n ) : hasImage ? (\n /*\n * width/height via style: the Image primitive types dimensions\n * differently per platform (web string vs native number).\n *\n * ⛔ `alt` IS REQUIRED HERE AND WAS MISSING — every Avatar with\n * a `src` warned, on every render. gluestack's own image creator\n * does `if (typeof alt !== 'string') console.warn('Please pass\n * alt prop to Image component')`, so the check is on the TYPE,\n * not on emptiness: a missing prop warns and an empty string\n * does not. Measured in AlphaMatch on 5 October 2026 — 21\n * warnings in a single sign-in from `AMTabBar`'s Me slot alone,\n * which is one Avatar.\n *\n * ⛔ AND IT IS EMPTY ON PURPOSE, NOT `ariaLabel`. The Box above\n * already carries `role=\"img\"` and `aria-label={ariaLabel}`, so\n * this image is PRESENTATION inside an element that is already\n * named; repeating the label here would announce the person's\n * name twice. Empty is the standing answer for a decorative\n * image, and it is this library's own: `PhoneInput` passes\n * `alt={countryISO ?? \"\"}` for exactly this reason.\n *\n * ⛔ `aria-hidden` IS THE OTHER HALF, AND `alt=\"\"` ALONE WAS NOT\n * ENOUGH — found by Codex, 5 October 2026. gluestack does not\n * only read `alt`; it also forces\n * `role={props.role || 'img'}`, so an empty alt leaves a\n * SECOND, NAMELESS image role sitting under the labelled Box.\n * On the web an `<img alt=\"\">` is decorative and harmless; on\n * React Native that role becomes `accessibilityRole=\"image\"`\n * and a screen reader can land on an unnamed image. Hiding the\n * node is what makes it presentational on both platforms —\n * RN maps `aria-hidden` to `accessibilityElementsHidden` on\n * iOS and `importantForAccessibility=\"no-hide-descendants\"` on\n * Android. `alt=\"\"` stays because it is what silences the\n * warning: gluestack checks `typeof alt !== 'string'`.\n *\n * ⚠️ `Gallery` HAS THE SAME MISSING `alt`, one file away, and is\n * NOT fixed here — it was outside what this change was opened\n * for. Recorded in the session report rather than swept in.\n */\n <Image\n src={src}\n alt=\"\"\n aria-hidden\n style={{width: px, height: px} as any}\n objectFit=\"cover\"\n />\n ) : showInitials ? (\n <Text\n color={initialsColor}\n fontSize={fontSize}\n fontWeight=\"700\"\n lineHeight={Math.round(fontSize * 1.2)}\n textAlign=\"center\"\n >\n {resolvedInitials}\n </Text>\n ) : showIcon ? (\n <Icon name={icon as never} size={iconSize} color=\"gray.500\" />\n ) : null}\n </Box>\n\n {/* Ring overlay (solid active ring) */}\n {ring && (\n <Box\n position=\"absolute\"\n top={0}\n right={0}\n bottom={0}\n left={0}\n borderRadius={radius}\n borderWidth={ringW}\n borderStyle=\"solid\"\n borderColor={ringColor}\n />\n )}\n\n {/* Badge OR presence dot (badge wins the corner) */}\n {badge != null ? (\n <Box position=\"absolute\" bottom={-2} right={-2} zIndex={2}>\n {badge}\n </Box>\n ) : status !== \"none\" ? (\n <Box\n position=\"absolute\"\n bottom={0}\n right={0}\n zIndex={2}\n width={dot}\n height={dot}\n borderRadius={dot}\n bgColor={statusColor}\n borderWidth={2}\n borderColor=\"surface-card\"\n />\n ) : null}\n </Box>\n );\n}\n\n/**\n * AvatarStack — overlapping row of avatars with a \"+N\" overflow tile.\n * Each avatar gets a surface-coloured cut-out ring so it reads cleanly\n * against the one behind it.\n *\n * <AvatarStack items={members} max={4} activeIndex={0} />\n */\nexport function AvatarStack(props: IAvatarStackProps) {\n const {mergedProps} = useComponentDefaults<IAvatarStackProps>(\"AvatarStack\", props);\n const {items, max = 4, size = \"md\", overlap = 0.35, activeIndex, ringColor = \"brand\", testID, ...rest} = mergedProps;\n\n const px = resolveSize(size);\n const clampedOverlap = Math.min(Math.max(overlap, 0), 0.9);\n const overlapPx = Math.round(px * clampedOverlap);\n const strokeW = px >= 56 ? 3 : 2;\n\n const visible = items.slice(0, max);\n const overflow = items.length - visible.length;\n\n const cell = (key: string, node: React.ReactNode, i: number) => (\n <Box\n key={key}\n marginLeft={i === 0 ? 0 : -overlapPx}\n zIndex={items.length - i}\n borderRadius={9999}\n borderWidth={strokeW}\n borderColor=\"surface-card\"\n bgColor=\"surface-card\"\n >\n {node}\n </Box>\n );\n\n const a11yProps = {\n role: \"group\",\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box flexDirection=\"row\" alignItems=\"center\" {...rest} {...(a11yProps as any)}>\n {visible.map((item, i) =>\n cell(\n `avatar-${i}`,\n <Avatar\n {...item}\n size={size}\n ring={i === activeIndex || item.ring}\n ringColor={item.ringColor ?? ringColor}\n />,\n i,\n ),\n )}\n {overflow > 0 && cell(\"avatar-overflow\", <Avatar initials={`+${overflow}`} size={size} color=\"ink.400\" />, visible.length)}\n </Box>\n );\n}\n\nexport default Avatar;\n"],"names":["useComponentDefaults","jsxs","Box","jsx","Icon","Image","Text"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import Image from '../../primitives/Image/index.js';
|
|
|
5
5
|
import { Icon } from '../../primitives/Icon/index.js';
|
|
6
6
|
import 'react';
|
|
7
7
|
import '../../contexts/DialogContext.js';
|
|
8
|
+
import '../../contexts/PermissionsContext.js';
|
|
8
9
|
import useComponentDefaults from '../../hooks/useComponentDefaults.js';
|
|
9
10
|
|
|
10
11
|
const SIZE_PX = { xs: 24, sm: 32, md: 40, lg: 56, xl: 72 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from \"react\";\nimport type {IAvatarProps, IAvatarStackProps, AvatarSize} from \"@lmb-it/kitsconcerto-types\";\nimport {Box, Text, Image, Icon} from \"../../primitives\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n/* ─── Size resolution ─────────────────────────────────────────── */\nconst SIZE_PX: Record<string, number> = {xs: 24, sm: 32, md: 40, lg: 56, xl: 72};\n\nfunction resolveSize(size: AvatarSize | undefined): number {\n if (typeof size === \"number\") return size;\n return SIZE_PX[size ?? \"md\"] ?? 40;\n}\n\n/* ─── Status dot → semantic token ─────────────────────────────── */\nconst STATUS_TOKENS: Record<string, string> = {\n online: \"success\",\n offline: \"gray.400\",\n away: \"warning\",\n busy: \"danger\",\n};\n\n/* ─── Deterministic monogram palette (all confirmed theme tokens) ─ */\nconst MONOGRAM_PALETTE = [\"brand\", \"primary.800\", \"success\", \"danger\", \"ink.700\"];\n\nfunction hashIndex(input: string, mod: number): number {\n let h = 0;\n for (let i = 0; i < input.length; i++) h = (h * 31 + input.charCodeAt(i)) >>> 0;\n return mod > 0 ? h % mod : 0;\n}\n\nfunction deriveInitials(name?: string, initials?: string): string {\n if (initials) return initials.slice(0, 3).toUpperCase();\n if (!name) return \"\";\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"\";\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return (parts[0]!.charAt(0) + parts[parts.length - 1]!.charAt(0)).toUpperCase();\n}\n\n/**\n * Avatar — image / monogram / icon identity tile.\n *\n * Pure presentational and cross-platform: composed from the `Box` + `Text` +\n * `Image` + `Icon` primitives, so it renders identically on web and native\n * with no platform split. Tappability is the caller's concern (wrap in a\n * Pressable / Button).\n *\n * <Avatar src=\"https://…/me.jpg\" size=\"lg\" />\n * <Avatar name=\"Fouad K\" status=\"online\" />\n * <Avatar initials=\"C\" masked /> // identity-masked (Flex)\n * <Avatar name=\"Acme\" shape=\"rounded\" badge={<Icon name=\"briefcase\" />} />\n */\nexport function Avatar(props: IAvatarProps) {\n const {mergedProps} = useComponentDefaults<IAvatarProps>(\"Avatar\", props);\n const {\n src,\n name,\n initials,\n icon,\n size = \"md\",\n shape = \"circle\",\n color,\n status = \"none\",\n ring = false,\n ringColor = \"brand\",\n masked = false,\n maskFillColor = \"indigo.600\",\n badge,\n alt,\n testID,\n ...rest\n } = mergedProps;\n\n const px = resolveSize(size);\n const radius = shape === \"circle\" ? px / 2 : Math.round(px * 0.28);\n const fontSize = Math.max(10, Math.round(px * 0.4));\n const iconSize = Math.round(px * 0.5);\n const dot = Math.max(8, Math.round(px * 0.28));\n const ringW = px >= 56 ? 3 : 2;\n\n const resolvedInitials = deriveInitials(name, initials);\n const hasImage = !!src;\n const showInitials = !hasImage && resolvedInitials.length > 0;\n const showIcon = !hasImage && !showInitials && icon != null;\n\n const monogramBg =\n color ?? (MONOGRAM_PALETTE[hashIndex(name ?? resolvedInitials, MONOGRAM_PALETTE.length)] ?? \"brand\");\n const surfaceBg = masked ? maskFillColor : hasImage ? \"gray.100\" : monogramBg;\n const initialsColor = \"#FFFFFF\";\n\n const statusColor = STATUS_TOKENS[status] ?? \"gray.400\";\n const ariaLabel = alt ?? name ?? \"avatar\";\n\n const a11yProps = {\n role: \"img\",\n \"aria-label\": ariaLabel,\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box\n position=\"relative\"\n width={px}\n height={px}\n {...rest}\n {...(a11yProps as any)}\n >\n {/* Surface (clips the image / centres the monogram).\n overflow:hidden only when an image is present — clipping the\n monogram <Text> cuts off the glyph tops on native. */}\n <Box\n width=\"100%\"\n height=\"100%\"\n borderRadius={radius}\n overflow={hasImage && !masked ? \"hidden\" : \"visible\"}\n alignItems=\"center\"\n justifyContent=\"center\"\n bgColor={surfaceBg}\n >\n {masked ? (\n <Icon name=\"user\" size={iconSize} color=\"#FFFFFF\" />\n ) : hasImage ? (\n /*\n * width/height via style: the Image primitive types dimensions\n * differently per platform (web string vs native number).\n *\n * ⛔ `alt` IS REQUIRED HERE AND WAS MISSING — every Avatar with\n * a `src` warned, on every render. gluestack's own image creator\n * does `if (typeof alt !== 'string') console.warn('Please pass\n * alt prop to Image component')`, so the check is on the TYPE,\n * not on emptiness: a missing prop warns and an empty string\n * does not. Measured in AlphaMatch on 5 October 2026 — 21\n * warnings in a single sign-in from `AMTabBar`'s Me slot alone,\n * which is one Avatar.\n *\n * ⛔ AND IT IS EMPTY ON PURPOSE, NOT `ariaLabel`. The Box above\n * already carries `role=\"img\"` and `aria-label={ariaLabel}`, so\n * this image is PRESENTATION inside an element that is already\n * named; repeating the label here would announce the person's\n * name twice. Empty is the standing answer for a decorative\n * image, and it is this library's own: `PhoneInput` passes\n * `alt={countryISO ?? \"\"}` for exactly this reason.\n *\n * ⛔ `aria-hidden` IS THE OTHER HALF, AND `alt=\"\"` ALONE WAS NOT\n * ENOUGH — found by Codex, 5 October 2026. gluestack does not\n * only read `alt`; it also forces\n * `role={props.role || 'img'}`, so an empty alt leaves a\n * SECOND, NAMELESS image role sitting under the labelled Box.\n * On the web an `<img alt=\"\">` is decorative and harmless; on\n * React Native that role becomes `accessibilityRole=\"image\"`\n * and a screen reader can land on an unnamed image. Hiding the\n * node is what makes it presentational on both platforms —\n * RN maps `aria-hidden` to `accessibilityElementsHidden` on\n * iOS and `importantForAccessibility=\"no-hide-descendants\"` on\n * Android. `alt=\"\"` stays because it is what silences the\n * warning: gluestack checks `typeof alt !== 'string'`.\n *\n * ⚠️ `Gallery` HAS THE SAME MISSING `alt`, one file away, and is\n * NOT fixed here — it was outside what this change was opened\n * for. Recorded in the session report rather than swept in.\n */\n <Image\n src={src}\n alt=\"\"\n aria-hidden\n style={{width: px, height: px} as any}\n objectFit=\"cover\"\n />\n ) : showInitials ? (\n <Text\n color={initialsColor}\n fontSize={fontSize}\n fontWeight=\"700\"\n lineHeight={Math.round(fontSize * 1.2)}\n textAlign=\"center\"\n >\n {resolvedInitials}\n </Text>\n ) : showIcon ? (\n <Icon name={icon as never} size={iconSize} color=\"gray.500\" />\n ) : null}\n </Box>\n\n {/* Ring overlay (solid active ring) */}\n {ring && (\n <Box\n position=\"absolute\"\n top={0}\n right={0}\n bottom={0}\n left={0}\n borderRadius={radius}\n borderWidth={ringW}\n borderStyle=\"solid\"\n borderColor={ringColor}\n />\n )}\n\n {/* Badge OR presence dot (badge wins the corner) */}\n {badge != null ? (\n <Box position=\"absolute\" bottom={-2} right={-2} zIndex={2}>\n {badge}\n </Box>\n ) : status !== \"none\" ? (\n <Box\n position=\"absolute\"\n bottom={0}\n right={0}\n zIndex={2}\n width={dot}\n height={dot}\n borderRadius={dot}\n bgColor={statusColor}\n borderWidth={2}\n borderColor=\"surface-card\"\n />\n ) : null}\n </Box>\n );\n}\n\n/**\n * AvatarStack — overlapping row of avatars with a \"+N\" overflow tile.\n * Each avatar gets a surface-coloured cut-out ring so it reads cleanly\n * against the one behind it.\n *\n * <AvatarStack items={members} max={4} activeIndex={0} />\n */\nexport function AvatarStack(props: IAvatarStackProps) {\n const {mergedProps} = useComponentDefaults<IAvatarStackProps>(\"AvatarStack\", props);\n const {items, max = 4, size = \"md\", overlap = 0.35, activeIndex, ringColor = \"brand\", testID, ...rest} = mergedProps;\n\n const px = resolveSize(size);\n const clampedOverlap = Math.min(Math.max(overlap, 0), 0.9);\n const overlapPx = Math.round(px * clampedOverlap);\n const strokeW = px >= 56 ? 3 : 2;\n\n const visible = items.slice(0, max);\n const overflow = items.length - visible.length;\n\n const cell = (key: string, node: React.ReactNode, i: number) => (\n <Box\n key={key}\n marginLeft={i === 0 ? 0 : -overlapPx}\n zIndex={items.length - i}\n borderRadius={9999}\n borderWidth={strokeW}\n borderColor=\"surface-card\"\n bgColor=\"surface-card\"\n >\n {node}\n </Box>\n );\n\n const a11yProps = {\n role: \"group\",\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box flexDirection=\"row\" alignItems=\"center\" {...rest} {...(a11yProps as any)}>\n {visible.map((item, i) =>\n cell(\n `avatar-${i}`,\n <Avatar\n {...item}\n size={size}\n ring={i === activeIndex || item.ring}\n ringColor={item.ringColor ?? ringColor}\n />,\n i,\n ),\n )}\n {overflow > 0 && cell(\"avatar-overflow\", <Avatar initials={`+${overflow}`} size={size} color=\"ink.400\" />, visible.length)}\n </Box>\n );\n}\n\nexport default Avatar;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/Avatar/index.tsx"],"sourcesContent":["import React from \"react\";\nimport type {IAvatarProps, IAvatarStackProps, AvatarSize} from \"@lmb-it/kitsconcerto-types\";\nimport {Box, Text, Image, Icon} from \"../../primitives\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n/* ─── Size resolution ─────────────────────────────────────────── */\nconst SIZE_PX: Record<string, number> = {xs: 24, sm: 32, md: 40, lg: 56, xl: 72};\n\nfunction resolveSize(size: AvatarSize | undefined): number {\n if (typeof size === \"number\") return size;\n return SIZE_PX[size ?? \"md\"] ?? 40;\n}\n\n/* ─── Status dot → semantic token ─────────────────────────────── */\nconst STATUS_TOKENS: Record<string, string> = {\n online: \"success\",\n offline: \"gray.400\",\n away: \"warning\",\n busy: \"danger\",\n};\n\n/* ─── Deterministic monogram palette (all confirmed theme tokens) ─ */\nconst MONOGRAM_PALETTE = [\"brand\", \"primary.800\", \"success\", \"danger\", \"ink.700\"];\n\nfunction hashIndex(input: string, mod: number): number {\n let h = 0;\n for (let i = 0; i < input.length; i++) h = (h * 31 + input.charCodeAt(i)) >>> 0;\n return mod > 0 ? h % mod : 0;\n}\n\nfunction deriveInitials(name?: string, initials?: string): string {\n if (initials) return initials.slice(0, 3).toUpperCase();\n if (!name) return \"\";\n const parts = name.trim().split(/\\s+/).filter(Boolean);\n if (parts.length === 0) return \"\";\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();\n return (parts[0]!.charAt(0) + parts[parts.length - 1]!.charAt(0)).toUpperCase();\n}\n\n/**\n * Avatar — image / monogram / icon identity tile.\n *\n * Pure presentational and cross-platform: composed from the `Box` + `Text` +\n * `Image` + `Icon` primitives, so it renders identically on web and native\n * with no platform split. Tappability is the caller's concern (wrap in a\n * Pressable / Button).\n *\n * <Avatar src=\"https://…/me.jpg\" size=\"lg\" />\n * <Avatar name=\"Fouad K\" status=\"online\" />\n * <Avatar initials=\"C\" masked /> // identity-masked (Flex)\n * <Avatar name=\"Acme\" shape=\"rounded\" badge={<Icon name=\"briefcase\" />} />\n */\nexport function Avatar(props: IAvatarProps) {\n const {mergedProps} = useComponentDefaults<IAvatarProps>(\"Avatar\", props);\n const {\n src,\n name,\n initials,\n icon,\n size = \"md\",\n shape = \"circle\",\n color,\n status = \"none\",\n ring = false,\n ringColor = \"brand\",\n masked = false,\n maskFillColor = \"indigo.600\",\n badge,\n alt,\n testID,\n ...rest\n } = mergedProps;\n\n const px = resolveSize(size);\n const radius = shape === \"circle\" ? px / 2 : Math.round(px * 0.28);\n const fontSize = Math.max(10, Math.round(px * 0.4));\n const iconSize = Math.round(px * 0.5);\n const dot = Math.max(8, Math.round(px * 0.28));\n const ringW = px >= 56 ? 3 : 2;\n\n const resolvedInitials = deriveInitials(name, initials);\n const hasImage = !!src;\n const showInitials = !hasImage && resolvedInitials.length > 0;\n const showIcon = !hasImage && !showInitials && icon != null;\n\n const monogramBg =\n color ?? (MONOGRAM_PALETTE[hashIndex(name ?? resolvedInitials, MONOGRAM_PALETTE.length)] ?? \"brand\");\n const surfaceBg = masked ? maskFillColor : hasImage ? \"gray.100\" : monogramBg;\n const initialsColor = \"#FFFFFF\";\n\n const statusColor = STATUS_TOKENS[status] ?? \"gray.400\";\n const ariaLabel = alt ?? name ?? \"avatar\";\n\n const a11yProps = {\n role: \"img\",\n \"aria-label\": ariaLabel,\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box\n position=\"relative\"\n width={px}\n height={px}\n {...rest}\n {...(a11yProps as any)}\n >\n {/* Surface (clips the image / centres the monogram).\n overflow:hidden only when an image is present — clipping the\n monogram <Text> cuts off the glyph tops on native. */}\n <Box\n width=\"100%\"\n height=\"100%\"\n borderRadius={radius}\n overflow={hasImage && !masked ? \"hidden\" : \"visible\"}\n alignItems=\"center\"\n justifyContent=\"center\"\n bgColor={surfaceBg}\n >\n {masked ? (\n <Icon name=\"user\" size={iconSize} color=\"#FFFFFF\" />\n ) : hasImage ? (\n /*\n * width/height via style: the Image primitive types dimensions\n * differently per platform (web string vs native number).\n *\n * ⛔ `alt` IS REQUIRED HERE AND WAS MISSING — every Avatar with\n * a `src` warned, on every render. gluestack's own image creator\n * does `if (typeof alt !== 'string') console.warn('Please pass\n * alt prop to Image component')`, so the check is on the TYPE,\n * not on emptiness: a missing prop warns and an empty string\n * does not. Measured in AlphaMatch on 5 October 2026 — 21\n * warnings in a single sign-in from `AMTabBar`'s Me slot alone,\n * which is one Avatar.\n *\n * ⛔ AND IT IS EMPTY ON PURPOSE, NOT `ariaLabel`. The Box above\n * already carries `role=\"img\"` and `aria-label={ariaLabel}`, so\n * this image is PRESENTATION inside an element that is already\n * named; repeating the label here would announce the person's\n * name twice. Empty is the standing answer for a decorative\n * image, and it is this library's own: `PhoneInput` passes\n * `alt={countryISO ?? \"\"}` for exactly this reason.\n *\n * ⛔ `aria-hidden` IS THE OTHER HALF, AND `alt=\"\"` ALONE WAS NOT\n * ENOUGH — found by Codex, 5 October 2026. gluestack does not\n * only read `alt`; it also forces\n * `role={props.role || 'img'}`, so an empty alt leaves a\n * SECOND, NAMELESS image role sitting under the labelled Box.\n * On the web an `<img alt=\"\">` is decorative and harmless; on\n * React Native that role becomes `accessibilityRole=\"image\"`\n * and a screen reader can land on an unnamed image. Hiding the\n * node is what makes it presentational on both platforms —\n * RN maps `aria-hidden` to `accessibilityElementsHidden` on\n * iOS and `importantForAccessibility=\"no-hide-descendants\"` on\n * Android. `alt=\"\"` stays because it is what silences the\n * warning: gluestack checks `typeof alt !== 'string'`.\n *\n * ⚠️ `Gallery` HAS THE SAME MISSING `alt`, one file away, and is\n * NOT fixed here — it was outside what this change was opened\n * for. Recorded in the session report rather than swept in.\n */\n <Image\n src={src}\n alt=\"\"\n aria-hidden\n style={{width: px, height: px} as any}\n objectFit=\"cover\"\n />\n ) : showInitials ? (\n <Text\n color={initialsColor}\n fontSize={fontSize}\n fontWeight=\"700\"\n lineHeight={Math.round(fontSize * 1.2)}\n textAlign=\"center\"\n >\n {resolvedInitials}\n </Text>\n ) : showIcon ? (\n <Icon name={icon as never} size={iconSize} color=\"gray.500\" />\n ) : null}\n </Box>\n\n {/* Ring overlay (solid active ring) */}\n {ring && (\n <Box\n position=\"absolute\"\n top={0}\n right={0}\n bottom={0}\n left={0}\n borderRadius={radius}\n borderWidth={ringW}\n borderStyle=\"solid\"\n borderColor={ringColor}\n />\n )}\n\n {/* Badge OR presence dot (badge wins the corner) */}\n {badge != null ? (\n <Box position=\"absolute\" bottom={-2} right={-2} zIndex={2}>\n {badge}\n </Box>\n ) : status !== \"none\" ? (\n <Box\n position=\"absolute\"\n bottom={0}\n right={0}\n zIndex={2}\n width={dot}\n height={dot}\n borderRadius={dot}\n bgColor={statusColor}\n borderWidth={2}\n borderColor=\"surface-card\"\n />\n ) : null}\n </Box>\n );\n}\n\n/**\n * AvatarStack — overlapping row of avatars with a \"+N\" overflow tile.\n * Each avatar gets a surface-coloured cut-out ring so it reads cleanly\n * against the one behind it.\n *\n * <AvatarStack items={members} max={4} activeIndex={0} />\n */\nexport function AvatarStack(props: IAvatarStackProps) {\n const {mergedProps} = useComponentDefaults<IAvatarStackProps>(\"AvatarStack\", props);\n const {items, max = 4, size = \"md\", overlap = 0.35, activeIndex, ringColor = \"brand\", testID, ...rest} = mergedProps;\n\n const px = resolveSize(size);\n const clampedOverlap = Math.min(Math.max(overlap, 0), 0.9);\n const overlapPx = Math.round(px * clampedOverlap);\n const strokeW = px >= 56 ? 3 : 2;\n\n const visible = items.slice(0, max);\n const overflow = items.length - visible.length;\n\n const cell = (key: string, node: React.ReactNode, i: number) => (\n <Box\n key={key}\n marginLeft={i === 0 ? 0 : -overlapPx}\n zIndex={items.length - i}\n borderRadius={9999}\n borderWidth={strokeW}\n borderColor=\"surface-card\"\n bgColor=\"surface-card\"\n >\n {node}\n </Box>\n );\n\n const a11yProps = {\n role: \"group\",\n ...(testID ? {testID, \"data-testid\": testID} : {}),\n } as Record<string, unknown>;\n\n return (\n <Box flexDirection=\"row\" alignItems=\"center\" {...rest} {...(a11yProps as any)}>\n {visible.map((item, i) =>\n cell(\n `avatar-${i}`,\n <Avatar\n {...item}\n size={size}\n ring={i === activeIndex || item.ring}\n ringColor={item.ringColor ?? ringColor}\n />,\n i,\n ),\n )}\n {overflow > 0 && cell(\"avatar-overflow\", <Avatar initials={`+${overflow}`} size={size} color=\"ink.400\" />, visible.length)}\n </Box>\n );\n}\n\nexport default Avatar;\n"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,7 @@ var useSeverityColors = require('../../hooks/useSeverityColors.cjs');
|
|
|
8
8
|
require('react');
|
|
9
9
|
var locale = require('../../hooks/locale.cjs');
|
|
10
10
|
require('../../contexts/DialogContext.cjs');
|
|
11
|
+
require('../../contexts/PermissionsContext.cjs');
|
|
11
12
|
var reactNative = require('react-native');
|
|
12
13
|
var KitsThemeProvider_native = require('../../contexts/Theme/KitsThemeProvider.cjs');
|
|
13
14
|
var index_native = require('../../primitives/Icon/index.cjs');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.cjs","sources":["../../../../src/components/Banner/banner.native.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flex, Text, Icon } from \"../../_compat\";\nimport {\n AlertTriangle,\n ArrowLeft,\n ArrowRight,\n CheckCircle2,\n Info,\n CircleX,\n X,\n} from \"lucide-react-native\";\nimport { useSeverityColors } from \"../../hooks/useSeverityColors\";\nimport { useKitsTheme } from \"../../contexts/Theme\";\nimport { useLanguage } from \"../../hooks\";\nimport type { BannerAction, IBannerProps, BannerStatus } from \"@lmb-it/kitsconcerto-types\";\nimport type { Severity } from \"@lmb-it/kitsconcerto-types\";\nimport { Pressable } from \"react-native\";\n\nconst icons: Record<string, any> = {\n error: CircleX,\n success: CheckCircle2,\n warning: AlertTriangle,\n info: Info,\n};\n\nfunction statusToSeverity(status: BannerStatus): Severity {\n if (status === \"error\") return \"danger\";\n return status;\n}\n\nconst Banner: React.FC<IBannerProps> = ({\n status: statusProp,\n headerTitle,\n headerIcon = true,\n title,\n description,\n withIcon = true,\n actions = [],\n onDismiss,\n children,\n className,\n textDirection,\n}) => {\n const { theme } = useKitsTheme();\n const { t, isRTL, isKeyExists } = useLanguage();\n const hasActions = actions.length > 0;\n const status = statusProp ?? (hasActions ? \"error\" : \"info\");\n const sev = useSeverityColors(statusToSeverity(status));\n\n /*\n * ⛔ THE HEADING IS THE CONSUMER'S TO WRITE. This read\n * `hasActions ? \"Action required…\" : headerTitle`, so a caller that passed\n * a translated `headerTitle` AND any actions had it thrown away and an\n * ENGLISH LITERAL rendered instead — with no prop, theme value or locale\n * key able to reach it.\n *\n * ⛔ FOUND IN AN ARABIC APP, 19 September 2026: AlphaMatch's Me tab showed\n * \"Action required\" in English on an otherwise fully Arabic screen, while\n * the app's OWN translated string for it sat unused one call away. Grepping\n * the app for the English text finds only its locale file, which is exactly\n * why it reads as an app bug and is not one.\n *\n * ⚠️ THE FALLBACK IS LOCALISED, BUT ONLY WHERE A TRANSLATION EXISTS.\n * `isKeyExists` is checked first so a language without the key keeps\n * today's English rather than rendering the raw key at a user — 38 of this\n * library's 40 locale files have not been given this string, and a visible\n * `actionRequired` would be a worse defect than the one being fixed.\n *\n * ⚠️ THE COUNT SUFFIX BELONGS TO THE FALLBACK, NOT TO THE CONSUMER. A title\n * someone wrote is a complete sentence; appending \"(3)\" to it is the\n * library talking over them.\n */\n const actionRequiredLabel = isKeyExists?.(\"actionRequired\")\n ? t(\"actionRequired\")\n : \"Action required\";\n const computedHeaderTitle = hasActions\n ? headerTitle ??\n `${actionRequiredLabel}${actions.length > 1 ? ` (${actions.length})` : \"\"}`\n : headerTitle;\n\n const hasHeader = !!computedHeaderTitle;\n const hasBody = !!(title || description || children);\n\n /*\n * ⛔ THE DIRECTION DEFAULTS TO THE ACTIVE LANGUAGE, NOT TO ENGLISH. This\n * prop defaulted to `\"ltr\"`, so every caller that did not pass it — which\n * was all of them — got a left-to-right banner in an Arabic app, and none\n * of them could find out. A library shipping to an RTL product reads the\n * direction itself; the prop stays, for the caller that needs to override.\n */\n const resolvedDirection = textDirection ?? (isRTL ? \"rtl\" : \"ltr\");\n const rowDirection = resolvedDirection === \"rtl\" ? \"row-reverse\" : \"row\";\n\n const headerIconNode = (() => {\n if (!headerIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n if (hasActions) return <Icon name={AlertTriangle} color={sev.solidText} size=\"sm\" />;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.solidText} size=\"sm\" /> : null;\n })();\n\n const bodyIconNode = (() => {\n if (!withIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.iconFg} size=\"sm\" /> : null;\n })();\n\n const renderActionRow = (bannerAction: BannerAction, index: number) => (\n <Flex\n key={bannerAction.id}\n flexDirection={rowDirection}\n alignItems=\"flex-start\"\n gap={10}\n style={{\n padding: 12,\n borderTopWidth: index > 0 ? 1 : 0,\n borderTopColor: sev.border,\n }}\n >\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n width: 28,\n height: 28,\n borderRadius: 8,\n backgroundColor: \"#fff\",\n borderWidth: 1,\n borderColor: sev.border,\n flexShrink: 0,\n }}\n >\n {bannerAction.icon ?? <Icon name={AlertTriangle} color={sev.iconFg} size=\"sm\" />}\n </Flex>\n <Flex flexDirection=\"column\" gap={2} style={{ flex: 1 }}>\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {bannerAction.label}\n </Text>\n {bannerAction.detail && (\n <Text size=\"xs\" style={{ color: sev.text, lineHeight: 17 }}>\n {bannerAction.detail}\n </Text>\n )}\n </Flex>\n {bannerAction.cta && (\n <Pressable\n onPress={bannerAction.onCta}\n style={{\n backgroundColor: sev.solid,\n borderRadius: 999,\n paddingHorizontal: 12,\n paddingVertical: 7,\n // ⛔ `rowDirection`, NOT a hardcoded \"row\". This was the\n // one row in the component that ignored the direction\n // every other row obeyed, so even a caller that DID\n // pass textDirection=\"rtl\" got this pill backwards.\n flexDirection: rowDirection,\n alignItems: \"center\",\n gap: 4,\n flexShrink: 0,\n }}\n >\n <Text\n fontWeight=\"bold\"\n size=\"xs\"\n style={{ color: sev.solidText }}\n >\n {bannerAction.cta}\n </Text>\n {/* ⛔ THE ARROW MEANS \"ONWARDS\", SO IT FOLLOWS THE READER.\n It was always ArrowRight, which in Arabic points back\n the way the eye came — on the one control the banner\n exists to get pressed. */}\n {resolvedDirection === \"rtl\" ? (\n <ArrowLeft size={12} color={sev.solidText} />\n ) : (\n <ArrowRight size={12} color={sev.solidText} />\n )}\n </Pressable>\n )}\n </Flex>\n );\n\n return (\n <Flex\n flexDirection=\"column\"\n className={className}\n style={{\n borderRadius: 8,\n overflow: \"hidden\",\n writingDirection: resolvedDirection,\n }}\n >\n {/* Header bar */}\n {hasHeader && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={6}\n style={{\n backgroundColor: sev.solid,\n paddingVertical: 8,\n paddingHorizontal: 12,\n }}\n >\n {headerIconNode}\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.solidText, flex: 1 }}>\n {computedHeaderTitle}\n </Text>\n {onDismiss && (\n <Pressable\n accessibilityLabel=\"Dismiss\"\n onPress={onDismiss}\n style={{\n width: 24,\n height: 24,\n borderRadius: 999,\n backgroundColor: \"rgba(255, 255, 255, 0.2)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <X size={14} color={sev.solidText} />\n </Pressable>\n )}\n </Flex>\n )}\n\n {/* Body section */}\n {hasActions ? (\n <Flex\n flexDirection=\"column\"\n style={{\n backgroundColor: sev.bgTint,\n }}\n >\n {actions.map(renderActionRow)}\n </Flex>\n ) : hasBody && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={12}\n style={{\n backgroundColor: sev.bgTint,\n padding: 12,\n justifyContent: \"space-between\",\n }}\n >\n <Flex flexDirection=\"column\" gap={4} style={{ flex: 1 }}>\n {(withIcon || title) && (\n <Flex flexDirection={rowDirection} alignItems=\"center\" gap={6}>\n {bodyIconNode}\n {title && (\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {title}\n </Text>\n )}\n </Flex>\n )}\n {description && (\n <Text size=\"xs\" style={{ color: sev.text }}>\n {description}\n </Text>\n )}\n {children}\n </Flex>\n </Flex>\n )}\n </Flex>\n );\n};\n\nexport default Banner;\n"],"names":["CircleX","CheckCircle2","AlertTriangle","Info","useKitsTheme","useLanguage","useSeverityColors","jsx","Fragment","Icon","index","jsxs","Flex","Text","Pressable","ArrowLeft","ArrowRight","X"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"banner.cjs","sources":["../../../../src/components/Banner/banner.native.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flex, Text, Icon } from \"../../_compat\";\nimport {\n AlertTriangle,\n ArrowLeft,\n ArrowRight,\n CheckCircle2,\n Info,\n CircleX,\n X,\n} from \"lucide-react-native\";\nimport { useSeverityColors } from \"../../hooks/useSeverityColors\";\nimport { useKitsTheme } from \"../../contexts/Theme\";\nimport { useLanguage } from \"../../hooks\";\nimport type { BannerAction, IBannerProps, BannerStatus } from \"@lmb-it/kitsconcerto-types\";\nimport type { Severity } from \"@lmb-it/kitsconcerto-types\";\nimport { Pressable } from \"react-native\";\n\nconst icons: Record<string, any> = {\n error: CircleX,\n success: CheckCircle2,\n warning: AlertTriangle,\n info: Info,\n};\n\nfunction statusToSeverity(status: BannerStatus): Severity {\n if (status === \"error\") return \"danger\";\n return status;\n}\n\nconst Banner: React.FC<IBannerProps> = ({\n status: statusProp,\n headerTitle,\n headerIcon = true,\n title,\n description,\n withIcon = true,\n actions = [],\n onDismiss,\n children,\n className,\n textDirection,\n}) => {\n const { theme } = useKitsTheme();\n const { t, isRTL, isKeyExists } = useLanguage();\n const hasActions = actions.length > 0;\n const status = statusProp ?? (hasActions ? \"error\" : \"info\");\n const sev = useSeverityColors(statusToSeverity(status));\n\n /*\n * ⛔ THE HEADING IS THE CONSUMER'S TO WRITE. This read\n * `hasActions ? \"Action required…\" : headerTitle`, so a caller that passed\n * a translated `headerTitle` AND any actions had it thrown away and an\n * ENGLISH LITERAL rendered instead — with no prop, theme value or locale\n * key able to reach it.\n *\n * ⛔ FOUND IN AN ARABIC APP, 19 September 2026: AlphaMatch's Me tab showed\n * \"Action required\" in English on an otherwise fully Arabic screen, while\n * the app's OWN translated string for it sat unused one call away. Grepping\n * the app for the English text finds only its locale file, which is exactly\n * why it reads as an app bug and is not one.\n *\n * ⚠️ THE FALLBACK IS LOCALISED, BUT ONLY WHERE A TRANSLATION EXISTS.\n * `isKeyExists` is checked first so a language without the key keeps\n * today's English rather than rendering the raw key at a user — 38 of this\n * library's 40 locale files have not been given this string, and a visible\n * `actionRequired` would be a worse defect than the one being fixed.\n *\n * ⚠️ THE COUNT SUFFIX BELONGS TO THE FALLBACK, NOT TO THE CONSUMER. A title\n * someone wrote is a complete sentence; appending \"(3)\" to it is the\n * library talking over them.\n */\n const actionRequiredLabel = isKeyExists?.(\"actionRequired\")\n ? t(\"actionRequired\")\n : \"Action required\";\n const computedHeaderTitle = hasActions\n ? headerTitle ??\n `${actionRequiredLabel}${actions.length > 1 ? ` (${actions.length})` : \"\"}`\n : headerTitle;\n\n const hasHeader = !!computedHeaderTitle;\n const hasBody = !!(title || description || children);\n\n /*\n * ⛔ THE DIRECTION DEFAULTS TO THE ACTIVE LANGUAGE, NOT TO ENGLISH. This\n * prop defaulted to `\"ltr\"`, so every caller that did not pass it — which\n * was all of them — got a left-to-right banner in an Arabic app, and none\n * of them could find out. A library shipping to an RTL product reads the\n * direction itself; the prop stays, for the caller that needs to override.\n */\n const resolvedDirection = textDirection ?? (isRTL ? \"rtl\" : \"ltr\");\n const rowDirection = resolvedDirection === \"rtl\" ? \"row-reverse\" : \"row\";\n\n const headerIconNode = (() => {\n if (!headerIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n if (hasActions) return <Icon name={AlertTriangle} color={sev.solidText} size=\"sm\" />;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.solidText} size=\"sm\" /> : null;\n })();\n\n const bodyIconNode = (() => {\n if (!withIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.iconFg} size=\"sm\" /> : null;\n })();\n\n const renderActionRow = (bannerAction: BannerAction, index: number) => (\n <Flex\n key={bannerAction.id}\n flexDirection={rowDirection}\n alignItems=\"flex-start\"\n gap={10}\n style={{\n padding: 12,\n borderTopWidth: index > 0 ? 1 : 0,\n borderTopColor: sev.border,\n }}\n >\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n width: 28,\n height: 28,\n borderRadius: 8,\n backgroundColor: \"#fff\",\n borderWidth: 1,\n borderColor: sev.border,\n flexShrink: 0,\n }}\n >\n {bannerAction.icon ?? <Icon name={AlertTriangle} color={sev.iconFg} size=\"sm\" />}\n </Flex>\n <Flex flexDirection=\"column\" gap={2} style={{ flex: 1 }}>\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {bannerAction.label}\n </Text>\n {bannerAction.detail && (\n <Text size=\"xs\" style={{ color: sev.text, lineHeight: 17 }}>\n {bannerAction.detail}\n </Text>\n )}\n </Flex>\n {bannerAction.cta && (\n <Pressable\n onPress={bannerAction.onCta}\n style={{\n backgroundColor: sev.solid,\n borderRadius: 999,\n paddingHorizontal: 12,\n paddingVertical: 7,\n // ⛔ `rowDirection`, NOT a hardcoded \"row\". This was the\n // one row in the component that ignored the direction\n // every other row obeyed, so even a caller that DID\n // pass textDirection=\"rtl\" got this pill backwards.\n flexDirection: rowDirection,\n alignItems: \"center\",\n gap: 4,\n flexShrink: 0,\n }}\n >\n <Text\n fontWeight=\"bold\"\n size=\"xs\"\n style={{ color: sev.solidText }}\n >\n {bannerAction.cta}\n </Text>\n {/* ⛔ THE ARROW MEANS \"ONWARDS\", SO IT FOLLOWS THE READER.\n It was always ArrowRight, which in Arabic points back\n the way the eye came — on the one control the banner\n exists to get pressed. */}\n {resolvedDirection === \"rtl\" ? (\n <ArrowLeft size={12} color={sev.solidText} />\n ) : (\n <ArrowRight size={12} color={sev.solidText} />\n )}\n </Pressable>\n )}\n </Flex>\n );\n\n return (\n <Flex\n flexDirection=\"column\"\n className={className}\n style={{\n borderRadius: 8,\n overflow: \"hidden\",\n writingDirection: resolvedDirection,\n }}\n >\n {/* Header bar */}\n {hasHeader && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={6}\n style={{\n backgroundColor: sev.solid,\n paddingVertical: 8,\n paddingHorizontal: 12,\n }}\n >\n {headerIconNode}\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.solidText, flex: 1 }}>\n {computedHeaderTitle}\n </Text>\n {onDismiss && (\n <Pressable\n accessibilityLabel=\"Dismiss\"\n onPress={onDismiss}\n style={{\n width: 24,\n height: 24,\n borderRadius: 999,\n backgroundColor: \"rgba(255, 255, 255, 0.2)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <X size={14} color={sev.solidText} />\n </Pressable>\n )}\n </Flex>\n )}\n\n {/* Body section */}\n {hasActions ? (\n <Flex\n flexDirection=\"column\"\n style={{\n backgroundColor: sev.bgTint,\n }}\n >\n {actions.map(renderActionRow)}\n </Flex>\n ) : hasBody && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={12}\n style={{\n backgroundColor: sev.bgTint,\n padding: 12,\n justifyContent: \"space-between\",\n }}\n >\n <Flex flexDirection=\"column\" gap={4} style={{ flex: 1 }}>\n {(withIcon || title) && (\n <Flex flexDirection={rowDirection} alignItems=\"center\" gap={6}>\n {bodyIconNode}\n {title && (\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {title}\n </Text>\n )}\n </Flex>\n )}\n {description && (\n <Text size=\"xs\" style={{ color: sev.text }}>\n {description}\n </Text>\n )}\n {children}\n </Flex>\n </Flex>\n )}\n </Flex>\n );\n};\n\nexport default Banner;\n"],"names":["CircleX","CheckCircle2","AlertTriangle","Info","useKitsTheme","useLanguage","useSeverityColors","jsx","Fragment","Icon","index","jsxs","Flex","Text","Pressable","ArrowLeft","ArrowRight","X"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ import { useSeverityColors } from '../../hooks/useSeverityColors.js';
|
|
|
4
4
|
import 'react';
|
|
5
5
|
import { useLanguage } from '../../hooks/locale.js';
|
|
6
6
|
import '../../contexts/DialogContext.js';
|
|
7
|
+
import '../../contexts/PermissionsContext.js';
|
|
7
8
|
import { Pressable } from 'react-native';
|
|
8
9
|
import { useKitsTheme } from '../../contexts/Theme/KitsThemeProvider.js';
|
|
9
10
|
import { Icon } from '../../primitives/Icon/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"banner.js","sources":["../../../../src/components/Banner/banner.native.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flex, Text, Icon } from \"../../_compat\";\nimport {\n AlertTriangle,\n ArrowLeft,\n ArrowRight,\n CheckCircle2,\n Info,\n CircleX,\n X,\n} from \"lucide-react-native\";\nimport { useSeverityColors } from \"../../hooks/useSeverityColors\";\nimport { useKitsTheme } from \"../../contexts/Theme\";\nimport { useLanguage } from \"../../hooks\";\nimport type { BannerAction, IBannerProps, BannerStatus } from \"@lmb-it/kitsconcerto-types\";\nimport type { Severity } from \"@lmb-it/kitsconcerto-types\";\nimport { Pressable } from \"react-native\";\n\nconst icons: Record<string, any> = {\n error: CircleX,\n success: CheckCircle2,\n warning: AlertTriangle,\n info: Info,\n};\n\nfunction statusToSeverity(status: BannerStatus): Severity {\n if (status === \"error\") return \"danger\";\n return status;\n}\n\nconst Banner: React.FC<IBannerProps> = ({\n status: statusProp,\n headerTitle,\n headerIcon = true,\n title,\n description,\n withIcon = true,\n actions = [],\n onDismiss,\n children,\n className,\n textDirection,\n}) => {\n const { theme } = useKitsTheme();\n const { t, isRTL, isKeyExists } = useLanguage();\n const hasActions = actions.length > 0;\n const status = statusProp ?? (hasActions ? \"error\" : \"info\");\n const sev = useSeverityColors(statusToSeverity(status));\n\n /*\n * ⛔ THE HEADING IS THE CONSUMER'S TO WRITE. This read\n * `hasActions ? \"Action required…\" : headerTitle`, so a caller that passed\n * a translated `headerTitle` AND any actions had it thrown away and an\n * ENGLISH LITERAL rendered instead — with no prop, theme value or locale\n * key able to reach it.\n *\n * ⛔ FOUND IN AN ARABIC APP, 19 September 2026: AlphaMatch's Me tab showed\n * \"Action required\" in English on an otherwise fully Arabic screen, while\n * the app's OWN translated string for it sat unused one call away. Grepping\n * the app for the English text finds only its locale file, which is exactly\n * why it reads as an app bug and is not one.\n *\n * ⚠️ THE FALLBACK IS LOCALISED, BUT ONLY WHERE A TRANSLATION EXISTS.\n * `isKeyExists` is checked first so a language without the key keeps\n * today's English rather than rendering the raw key at a user — 38 of this\n * library's 40 locale files have not been given this string, and a visible\n * `actionRequired` would be a worse defect than the one being fixed.\n *\n * ⚠️ THE COUNT SUFFIX BELONGS TO THE FALLBACK, NOT TO THE CONSUMER. A title\n * someone wrote is a complete sentence; appending \"(3)\" to it is the\n * library talking over them.\n */\n const actionRequiredLabel = isKeyExists?.(\"actionRequired\")\n ? t(\"actionRequired\")\n : \"Action required\";\n const computedHeaderTitle = hasActions\n ? headerTitle ??\n `${actionRequiredLabel}${actions.length > 1 ? ` (${actions.length})` : \"\"}`\n : headerTitle;\n\n const hasHeader = !!computedHeaderTitle;\n const hasBody = !!(title || description || children);\n\n /*\n * ⛔ THE DIRECTION DEFAULTS TO THE ACTIVE LANGUAGE, NOT TO ENGLISH. This\n * prop defaulted to `\"ltr\"`, so every caller that did not pass it — which\n * was all of them — got a left-to-right banner in an Arabic app, and none\n * of them could find out. A library shipping to an RTL product reads the\n * direction itself; the prop stays, for the caller that needs to override.\n */\n const resolvedDirection = textDirection ?? (isRTL ? \"rtl\" : \"ltr\");\n const rowDirection = resolvedDirection === \"rtl\" ? \"row-reverse\" : \"row\";\n\n const headerIconNode = (() => {\n if (!headerIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n if (hasActions) return <Icon name={AlertTriangle} color={sev.solidText} size=\"sm\" />;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.solidText} size=\"sm\" /> : null;\n })();\n\n const bodyIconNode = (() => {\n if (!withIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.iconFg} size=\"sm\" /> : null;\n })();\n\n const renderActionRow = (bannerAction: BannerAction, index: number) => (\n <Flex\n key={bannerAction.id}\n flexDirection={rowDirection}\n alignItems=\"flex-start\"\n gap={10}\n style={{\n padding: 12,\n borderTopWidth: index > 0 ? 1 : 0,\n borderTopColor: sev.border,\n }}\n >\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n width: 28,\n height: 28,\n borderRadius: 8,\n backgroundColor: \"#fff\",\n borderWidth: 1,\n borderColor: sev.border,\n flexShrink: 0,\n }}\n >\n {bannerAction.icon ?? <Icon name={AlertTriangle} color={sev.iconFg} size=\"sm\" />}\n </Flex>\n <Flex flexDirection=\"column\" gap={2} style={{ flex: 1 }}>\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {bannerAction.label}\n </Text>\n {bannerAction.detail && (\n <Text size=\"xs\" style={{ color: sev.text, lineHeight: 17 }}>\n {bannerAction.detail}\n </Text>\n )}\n </Flex>\n {bannerAction.cta && (\n <Pressable\n onPress={bannerAction.onCta}\n style={{\n backgroundColor: sev.solid,\n borderRadius: 999,\n paddingHorizontal: 12,\n paddingVertical: 7,\n // ⛔ `rowDirection`, NOT a hardcoded \"row\". This was the\n // one row in the component that ignored the direction\n // every other row obeyed, so even a caller that DID\n // pass textDirection=\"rtl\" got this pill backwards.\n flexDirection: rowDirection,\n alignItems: \"center\",\n gap: 4,\n flexShrink: 0,\n }}\n >\n <Text\n fontWeight=\"bold\"\n size=\"xs\"\n style={{ color: sev.solidText }}\n >\n {bannerAction.cta}\n </Text>\n {/* ⛔ THE ARROW MEANS \"ONWARDS\", SO IT FOLLOWS THE READER.\n It was always ArrowRight, which in Arabic points back\n the way the eye came — on the one control the banner\n exists to get pressed. */}\n {resolvedDirection === \"rtl\" ? (\n <ArrowLeft size={12} color={sev.solidText} />\n ) : (\n <ArrowRight size={12} color={sev.solidText} />\n )}\n </Pressable>\n )}\n </Flex>\n );\n\n return (\n <Flex\n flexDirection=\"column\"\n className={className}\n style={{\n borderRadius: 8,\n overflow: \"hidden\",\n writingDirection: resolvedDirection,\n }}\n >\n {/* Header bar */}\n {hasHeader && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={6}\n style={{\n backgroundColor: sev.solid,\n paddingVertical: 8,\n paddingHorizontal: 12,\n }}\n >\n {headerIconNode}\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.solidText, flex: 1 }}>\n {computedHeaderTitle}\n </Text>\n {onDismiss && (\n <Pressable\n accessibilityLabel=\"Dismiss\"\n onPress={onDismiss}\n style={{\n width: 24,\n height: 24,\n borderRadius: 999,\n backgroundColor: \"rgba(255, 255, 255, 0.2)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <X size={14} color={sev.solidText} />\n </Pressable>\n )}\n </Flex>\n )}\n\n {/* Body section */}\n {hasActions ? (\n <Flex\n flexDirection=\"column\"\n style={{\n backgroundColor: sev.bgTint,\n }}\n >\n {actions.map(renderActionRow)}\n </Flex>\n ) : hasBody && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={12}\n style={{\n backgroundColor: sev.bgTint,\n padding: 12,\n justifyContent: \"space-between\",\n }}\n >\n <Flex flexDirection=\"column\" gap={4} style={{ flex: 1 }}>\n {(withIcon || title) && (\n <Flex flexDirection={rowDirection} alignItems=\"center\" gap={6}>\n {bodyIconNode}\n {title && (\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {title}\n </Text>\n )}\n </Flex>\n )}\n {description && (\n <Text size=\"xs\" style={{ color: sev.text }}>\n {description}\n </Text>\n )}\n {children}\n </Flex>\n </Flex>\n )}\n </Flex>\n );\n};\n\nexport default Banner;\n"],"names":[],"mappings":";;;;;;;;;;;;AAkBA,MAAM,KAAA,GAA6B;AAAA,EAC/B,KAAA,EAAO,OAAA;AAAA,EACP,OAAA,EAAS,YAAA;AAAA,EACT,OAAA,EAAS,aAAA;AAAA,EACT,IAAA,EAAM;AACV,CAAA;AAEA,SAAS,iBAAiB,MAAA,EAAgC;AACtD,EAAA,IAAI,MAAA,KAAW,SAAS,OAAO,QAAA;AAC/B,EAAA,OAAO,MAAA;AACX;AAEA,MAAM,SAAiC,CAAC;AAAA,EACpC,MAAA,EAAQ,UAAA;AAAA,EACR,WAAA;AAAA,EACA,UAAA,GAAa,IAAA;AAAA,EACb,KAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA,GAAW,IAAA;AAAA,EACX,UAAU,EAAC;AAAA,EACX,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACJ,CAAA,KAAM;AACF,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,YAAA,EAAa;AAC/B,EAAA,MAAM,EAAE,CAAA,EAAG,KAAA,EAAO,WAAA,KAAgB,WAAA,EAAY;AAC9C,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,GAAS,CAAA;AACpC,EAAA,MAAM,MAAA,GAAS,UAAA,KAAe,UAAA,GAAa,OAAA,GAAU,MAAA,CAAA;AACrD,EAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAyBtD,EAAA,MAAM,sBAAsB,WAAA,GAAc,gBAAgB,CAAA,GACpD,CAAA,CAAE,gBAAgB,CAAA,GAClB,iBAAA;AACN,EAAA,MAAM,mBAAA,GAAsB,UAAA,GACtB,WAAA,IACA,CAAA,EAAG,mBAAmB,CAAA,EAAG,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,CAAA,EAAA,EAAK,OAAA,CAAQ,MAAM,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,CAAA,GACzE,WAAA;AAEN,EAAA,MAAM,SAAA,GAAY,CAAC,CAAC,mBAAA;AACpB,EAAA,MAAM,OAAA,GAAU,CAAC,EAAE,KAAA,IAAS,WAAA,IAAe,QAAA,CAAA;AAS3C,EAAA,MAAM,iBAAA,GAAoB,aAAA,KAAkB,KAAA,GAAQ,KAAA,GAAQ,KAAA,CAAA;AAC5D,EAAA,MAAM,YAAA,GAAe,iBAAA,KAAsB,KAAA,GAAQ,aAAA,GAAgB,KAAA;AAEnE,EAAA,MAAM,kBAAkB,MAAM;AAC1B,IAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AACxB,IAAA,IAAI,MAAA,KAAW,WAAW,KAAA,CAAM,MAAA,CAAO,MAAM,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,KAAA,CAAM,MAAA,CAAO,IAAA,EAAK,CAAA;AACzE,IAAA,IAAI,UAAA,EAAY,uBAAO,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,eAAe,KAAA,EAAO,GAAA,CAAI,SAAA,EAAW,IAAA,EAAK,IAAA,EAAK,CAAA;AAClF,IAAA,MAAM,QAAA,GAAW,MAAM,MAAM,CAAA;AAC7B,IAAA,OAAO,QAAA,mBAAW,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,QAAA,EAAU,OAAO,GAAA,CAAI,SAAA,EAAW,IAAA,EAAK,IAAA,EAAK,CAAA,GAAK,IAAA;AAAA,EACjF,CAAA,GAAG;AAEH,EAAA,MAAM,gBAAgB,MAAM;AACxB,IAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AACtB,IAAA,IAAI,MAAA,KAAW,WAAW,KAAA,CAAM,MAAA,CAAO,MAAM,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,KAAA,CAAM,MAAA,CAAO,IAAA,EAAK,CAAA;AACzE,IAAA,MAAM,QAAA,GAAW,MAAM,MAAM,CAAA;AAC7B,IAAA,OAAO,QAAA,mBAAW,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,QAAA,EAAU,OAAO,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAK,IAAA,EAAK,CAAA,GAAK,IAAA;AAAA,EAC9E,CAAA,GAAG;AAEH,EAAA,MAAM,eAAA,GAAkB,CAAC,YAAA,EAA4B,KAAA,qBACjD,IAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MAEG,aAAA,EAAe,YAAA;AAAA,MACf,UAAA,EAAW,YAAA;AAAA,MACX,GAAA,EAAK,EAAA;AAAA,MACL,KAAA,EAAO;AAAA,QACH,OAAA,EAAS,EAAA;AAAA,QACT,cAAA,EAAgB,KAAA,GAAQ,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,QAChC,gBAAgB,GAAA,CAAI;AAAA,OACxB;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,UAAA,EAAW,QAAA;AAAA,YACX,cAAA,EAAe,QAAA;AAAA,YACf,KAAA,EAAO;AAAA,cACH,KAAA,EAAO,EAAA;AAAA,cACP,MAAA,EAAQ,EAAA;AAAA,cACR,YAAA,EAAc,CAAA;AAAA,cACd,eAAA,EAAiB,MAAA;AAAA,cACjB,WAAA,EAAa,CAAA;AAAA,cACb,aAAa,GAAA,CAAI,MAAA;AAAA,cACjB,UAAA,EAAY;AAAA,aAChB;AAAA,YAEC,QAAA,EAAA,YAAA,CAAa,IAAA,oBAAQ,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,eAAe,KAAA,EAAO,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAK,IAAA,EAAK;AAAA;AAAA,SAClF;AAAA,wBACA,IAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAc,QAAA,EAAS,GAAA,EAAK,GAAG,KAAA,EAAO,EAAE,IAAA,EAAM,CAAA,EAAE,EAClD,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,UAAA,EAAW,MAAA,EAAO,IAAA,EAAK,IAAA,EAAK,KAAA,EAAO,EAAE,KAAA,EAAO,GAAA,CAAI,IAAA,EAAK,EACtD,QAAA,EAAA,YAAA,CAAa,KAAA,EAClB,CAAA;AAAA,UACC,YAAA,CAAa,MAAA,oBACV,GAAA,CAAC,IAAA,EAAA,EAAK,MAAK,IAAA,EAAK,KAAA,EAAO,EAAE,KAAA,EAAO,IAAI,IAAA,EAAM,UAAA,EAAY,EAAA,EAAG,EACpD,uBAAa,MAAA,EAClB;AAAA,SAAA,EAER,CAAA;AAAA,QACC,aAAa,GAAA,oBACV,IAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACG,SAAS,YAAA,CAAa,KAAA;AAAA,YACtB,KAAA,EAAO;AAAA,cACH,iBAAiB,GAAA,CAAI,KAAA;AAAA,cACrB,YAAA,EAAc,GAAA;AAAA,cACd,iBAAA,EAAmB,EAAA;AAAA,cACnB,eAAA,EAAiB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAKjB,aAAA,EAAe,YAAA;AAAA,cACf,UAAA,EAAY,QAAA;AAAA,cACZ,GAAA,EAAK,CAAA;AAAA,cACL,UAAA,EAAY;AAAA,aAChB;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAA,GAAA;AAAA,gBAAC,IAAA;AAAA,gBAAA;AAAA,kBACG,UAAA,EAAW,MAAA;AAAA,kBACX,IAAA,EAAK,IAAA;AAAA,kBACL,KAAA,EAAO,EAAE,KAAA,EAAO,GAAA,CAAI,SAAA,EAAU;AAAA,kBAE7B,QAAA,EAAA,YAAA,CAAa;AAAA;AAAA,eAClB;AAAA,cAKC,sBAAsB,KAAA,mBACnB,GAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAM,IAAI,KAAA,EAAO,GAAA,CAAI,SAAA,EAAW,CAAA,uBAE1C,UAAA,EAAA,EAAW,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,IAAI,SAAA,EAAW;AAAA;AAAA;AAAA;AAEpD;AAAA,KAAA;AAAA,IArEC,YAAA,CAAa;AAAA,GAuEtB;AAGJ,EAAA,uBACI,IAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACG,aAAA,EAAc,QAAA;AAAA,MACd,SAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACH,YAAA,EAAc,CAAA;AAAA,QACd,QAAA,EAAU,QAAA;AAAA,QACV,gBAAA,EAAkB;AAAA,OACtB;AAAA,MAGC,QAAA,EAAA;AAAA,QAAA,SAAA,oBACG,IAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,aAAA,EAAe,YAAA;AAAA,YACf,UAAA,EAAW,QAAA;AAAA,YACX,GAAA,EAAK,CAAA;AAAA,YACL,KAAA,EAAO;AAAA,cACH,iBAAiB,GAAA,CAAI,KAAA;AAAA,cACrB,eAAA,EAAiB,CAAA;AAAA,cACjB,iBAAA,EAAmB;AAAA,aACvB;AAAA,YAEC,QAAA,EAAA;AAAA,cAAA,cAAA;AAAA,8BACD,GAAA,CAAC,IAAA,EAAA,EAAK,UAAA,EAAW,MAAA,EAAO,MAAK,IAAA,EAAK,KAAA,EAAO,EAAE,KAAA,EAAO,GAAA,CAAI,SAAA,EAAW,IAAA,EAAM,CAAA,IAClE,QAAA,EAAA,mBAAA,EACL,CAAA;AAAA,cACC,SAAA,oBACG,GAAA;AAAA,gBAAC,SAAA;AAAA,gBAAA;AAAA,kBACG,kBAAA,EAAmB,SAAA;AAAA,kBACnB,OAAA,EAAS,SAAA;AAAA,kBACT,KAAA,EAAO;AAAA,oBACH,KAAA,EAAO,EAAA;AAAA,oBACP,MAAA,EAAQ,EAAA;AAAA,oBACR,YAAA,EAAc,GAAA;AAAA,oBACd,eAAA,EAAiB,0BAAA;AAAA,oBACjB,UAAA,EAAY,QAAA;AAAA,oBACZ,cAAA,EAAgB;AAAA,mBACpB;AAAA,kBAEA,8BAAC,CAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI,KAAA,EAAO,IAAI,SAAA,EAAW;AAAA;AAAA;AACvC;AAAA;AAAA,SAER;AAAA,QAIH,UAAA,mBACG,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,aAAA,EAAc,QAAA;AAAA,YACd,KAAA,EAAO;AAAA,cACH,iBAAiB,GAAA,CAAI;AAAA,aACzB;AAAA,YAEC,QAAA,EAAA,OAAA,CAAQ,IAAI,eAAe;AAAA;AAAA,YAEhC,OAAA,oBACA,GAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,aAAA,EAAe,YAAA;AAAA,YACf,UAAA,EAAW,QAAA;AAAA,YACX,GAAA,EAAK,EAAA;AAAA,YACL,KAAA,EAAO;AAAA,cACH,iBAAiB,GAAA,CAAI,MAAA;AAAA,cACrB,OAAA,EAAS,EAAA;AAAA,cACT,cAAA,EAAgB;AAAA,aACpB;AAAA,YAEA,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAc,QAAA,EAAS,GAAA,EAAK,GAAG,KAAA,EAAO,EAAE,IAAA,EAAM,CAAA,EAAE,EAChD,QAAA,EAAA;AAAA,cAAA,CAAA,QAAA,IAAY,KAAA,0BACT,IAAA,EAAA,EAAK,aAAA,EAAe,cAAc,UAAA,EAAW,QAAA,EAAS,KAAK,CAAA,EACvD,QAAA,EAAA;AAAA,gBAAA,YAAA;AAAA,gBACA,KAAA,oBACG,GAAA,CAAC,IAAA,EAAA,EAAK,UAAA,EAAW,MAAA,EAAO,IAAA,EAAK,IAAA,EAAK,KAAA,EAAO,EAAE,KAAA,EAAO,GAAA,CAAI,IAAA,IACjD,QAAA,EAAA,KAAA,EACL;AAAA,eAAA,EAER,CAAA;AAAA,cAEH,WAAA,oBACG,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,IAAA,EAAK,KAAA,EAAO,EAAE,KAAA,EAAO,GAAA,CAAI,IAAA,EAAK,EACpC,QAAA,EAAA,WAAA,EACL,CAAA;AAAA,cAEH;AAAA,aAAA,EACL;AAAA;AAAA;AACJ;AAAA;AAAA,GAER;AAER;;;;"}
|
|
1
|
+
{"version":3,"file":"banner.js","sources":["../../../../src/components/Banner/banner.native.tsx"],"sourcesContent":["import React from \"react\";\nimport { Flex, Text, Icon } from \"../../_compat\";\nimport {\n AlertTriangle,\n ArrowLeft,\n ArrowRight,\n CheckCircle2,\n Info,\n CircleX,\n X,\n} from \"lucide-react-native\";\nimport { useSeverityColors } from \"../../hooks/useSeverityColors\";\nimport { useKitsTheme } from \"../../contexts/Theme\";\nimport { useLanguage } from \"../../hooks\";\nimport type { BannerAction, IBannerProps, BannerStatus } from \"@lmb-it/kitsconcerto-types\";\nimport type { Severity } from \"@lmb-it/kitsconcerto-types\";\nimport { Pressable } from \"react-native\";\n\nconst icons: Record<string, any> = {\n error: CircleX,\n success: CheckCircle2,\n warning: AlertTriangle,\n info: Info,\n};\n\nfunction statusToSeverity(status: BannerStatus): Severity {\n if (status === \"error\") return \"danger\";\n return status;\n}\n\nconst Banner: React.FC<IBannerProps> = ({\n status: statusProp,\n headerTitle,\n headerIcon = true,\n title,\n description,\n withIcon = true,\n actions = [],\n onDismiss,\n children,\n className,\n textDirection,\n}) => {\n const { theme } = useKitsTheme();\n const { t, isRTL, isKeyExists } = useLanguage();\n const hasActions = actions.length > 0;\n const status = statusProp ?? (hasActions ? \"error\" : \"info\");\n const sev = useSeverityColors(statusToSeverity(status));\n\n /*\n * ⛔ THE HEADING IS THE CONSUMER'S TO WRITE. This read\n * `hasActions ? \"Action required…\" : headerTitle`, so a caller that passed\n * a translated `headerTitle` AND any actions had it thrown away and an\n * ENGLISH LITERAL rendered instead — with no prop, theme value or locale\n * key able to reach it.\n *\n * ⛔ FOUND IN AN ARABIC APP, 19 September 2026: AlphaMatch's Me tab showed\n * \"Action required\" in English on an otherwise fully Arabic screen, while\n * the app's OWN translated string for it sat unused one call away. Grepping\n * the app for the English text finds only its locale file, which is exactly\n * why it reads as an app bug and is not one.\n *\n * ⚠️ THE FALLBACK IS LOCALISED, BUT ONLY WHERE A TRANSLATION EXISTS.\n * `isKeyExists` is checked first so a language without the key keeps\n * today's English rather than rendering the raw key at a user — 38 of this\n * library's 40 locale files have not been given this string, and a visible\n * `actionRequired` would be a worse defect than the one being fixed.\n *\n * ⚠️ THE COUNT SUFFIX BELONGS TO THE FALLBACK, NOT TO THE CONSUMER. A title\n * someone wrote is a complete sentence; appending \"(3)\" to it is the\n * library talking over them.\n */\n const actionRequiredLabel = isKeyExists?.(\"actionRequired\")\n ? t(\"actionRequired\")\n : \"Action required\";\n const computedHeaderTitle = hasActions\n ? headerTitle ??\n `${actionRequiredLabel}${actions.length > 1 ? ` (${actions.length})` : \"\"}`\n : headerTitle;\n\n const hasHeader = !!computedHeaderTitle;\n const hasBody = !!(title || description || children);\n\n /*\n * ⛔ THE DIRECTION DEFAULTS TO THE ACTIVE LANGUAGE, NOT TO ENGLISH. This\n * prop defaulted to `\"ltr\"`, so every caller that did not pass it — which\n * was all of them — got a left-to-right banner in an Arabic app, and none\n * of them could find out. A library shipping to an RTL product reads the\n * direction itself; the prop stays, for the caller that needs to override.\n */\n const resolvedDirection = textDirection ?? (isRTL ? \"rtl\" : \"ltr\");\n const rowDirection = resolvedDirection === \"rtl\" ? \"row-reverse\" : \"row\";\n\n const headerIconNode = (() => {\n if (!headerIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n if (hasActions) return <Icon name={AlertTriangle} color={sev.solidText} size=\"sm\" />;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.solidText} size=\"sm\" /> : null;\n })();\n\n const bodyIconNode = (() => {\n if (!withIcon) return null;\n if (status === \"brand\" && theme.config.logo) return <>{theme.config.logo}</>;\n const IconComp = icons[status];\n return IconComp ? <Icon name={IconComp} color={sev.iconFg} size=\"sm\" /> : null;\n })();\n\n const renderActionRow = (bannerAction: BannerAction, index: number) => (\n <Flex\n key={bannerAction.id}\n flexDirection={rowDirection}\n alignItems=\"flex-start\"\n gap={10}\n style={{\n padding: 12,\n borderTopWidth: index > 0 ? 1 : 0,\n borderTopColor: sev.border,\n }}\n >\n <Flex\n alignItems=\"center\"\n justifyContent=\"center\"\n style={{\n width: 28,\n height: 28,\n borderRadius: 8,\n backgroundColor: \"#fff\",\n borderWidth: 1,\n borderColor: sev.border,\n flexShrink: 0,\n }}\n >\n {bannerAction.icon ?? <Icon name={AlertTriangle} color={sev.iconFg} size=\"sm\" />}\n </Flex>\n <Flex flexDirection=\"column\" gap={2} style={{ flex: 1 }}>\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {bannerAction.label}\n </Text>\n {bannerAction.detail && (\n <Text size=\"xs\" style={{ color: sev.text, lineHeight: 17 }}>\n {bannerAction.detail}\n </Text>\n )}\n </Flex>\n {bannerAction.cta && (\n <Pressable\n onPress={bannerAction.onCta}\n style={{\n backgroundColor: sev.solid,\n borderRadius: 999,\n paddingHorizontal: 12,\n paddingVertical: 7,\n // ⛔ `rowDirection`, NOT a hardcoded \"row\". This was the\n // one row in the component that ignored the direction\n // every other row obeyed, so even a caller that DID\n // pass textDirection=\"rtl\" got this pill backwards.\n flexDirection: rowDirection,\n alignItems: \"center\",\n gap: 4,\n flexShrink: 0,\n }}\n >\n <Text\n fontWeight=\"bold\"\n size=\"xs\"\n style={{ color: sev.solidText }}\n >\n {bannerAction.cta}\n </Text>\n {/* ⛔ THE ARROW MEANS \"ONWARDS\", SO IT FOLLOWS THE READER.\n It was always ArrowRight, which in Arabic points back\n the way the eye came — on the one control the banner\n exists to get pressed. */}\n {resolvedDirection === \"rtl\" ? (\n <ArrowLeft size={12} color={sev.solidText} />\n ) : (\n <ArrowRight size={12} color={sev.solidText} />\n )}\n </Pressable>\n )}\n </Flex>\n );\n\n return (\n <Flex\n flexDirection=\"column\"\n className={className}\n style={{\n borderRadius: 8,\n overflow: \"hidden\",\n writingDirection: resolvedDirection,\n }}\n >\n {/* Header bar */}\n {hasHeader && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={6}\n style={{\n backgroundColor: sev.solid,\n paddingVertical: 8,\n paddingHorizontal: 12,\n }}\n >\n {headerIconNode}\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.solidText, flex: 1 }}>\n {computedHeaderTitle}\n </Text>\n {onDismiss && (\n <Pressable\n accessibilityLabel=\"Dismiss\"\n onPress={onDismiss}\n style={{\n width: 24,\n height: 24,\n borderRadius: 999,\n backgroundColor: \"rgba(255, 255, 255, 0.2)\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n <X size={14} color={sev.solidText} />\n </Pressable>\n )}\n </Flex>\n )}\n\n {/* Body section */}\n {hasActions ? (\n <Flex\n flexDirection=\"column\"\n style={{\n backgroundColor: sev.bgTint,\n }}\n >\n {actions.map(renderActionRow)}\n </Flex>\n ) : hasBody && (\n <Flex\n flexDirection={rowDirection}\n alignItems=\"center\"\n gap={12}\n style={{\n backgroundColor: sev.bgTint,\n padding: 12,\n justifyContent: \"space-between\",\n }}\n >\n <Flex flexDirection=\"column\" gap={4} style={{ flex: 1 }}>\n {(withIcon || title) && (\n <Flex flexDirection={rowDirection} alignItems=\"center\" gap={6}>\n {bodyIconNode}\n {title && (\n <Text fontWeight=\"bold\" size=\"sm\" style={{ color: sev.text }}>\n {title}\n </Text>\n )}\n </Flex>\n )}\n {description && (\n <Text size=\"xs\" style={{ color: sev.text }}>\n {description}\n </Text>\n )}\n {children}\n </Flex>\n </Flex>\n )}\n </Flex>\n );\n};\n\nexport default Banner;\n"],"names":[],"mappings":"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"}
|
|
@@ -88,6 +88,7 @@ var index$1 = require('../../primitives/Box/index.cjs');
|
|
|
88
88
|
var index_native = require('../../primitives/Icon/index.cjs');
|
|
89
89
|
var index = require('../../layout/Flex/index.cjs');
|
|
90
90
|
require('../../contexts/DialogContext.cjs');
|
|
91
|
+
require('../../contexts/PermissionsContext.cjs');
|
|
91
92
|
var useComponentDefaults = require('../../hooks/useComponentDefaults.cjs');
|
|
92
93
|
|
|
93
94
|
const BAR_MIN_HEIGHT = 60;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../../../src/components/BottomTabBar/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport {Pressable, Text, View} from \"react-native\";\nimport {useSafeAreaInsets} from \"react-native-safe-area-context\";\nimport {resolveThemeTokenForNative} from \"@lmb-it/kitsconcertomobile\";\nimport useRtlLineHeight from \"../../hooks/useRtlLineHeight\";\nimport type {IBottomTabBarProps, ITabBarItem} from \"@lmb-it/kitsconcerto-types\";\nimport {Icon} from \"../../primitives\";\nimport {Box} from \"../../primitives\";\nimport Flex from \"../../layout/Flex\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n// Mirrors the app's AMTabBar geometry (App/src/components/shared/layout).\nconst BAR_MIN_HEIGHT = 60;\nconst FAB_SIZE = 56;\n\nfunction Badge({badge, barBg, dangerColor}: {badge: number | boolean; barBg: string; dangerColor: string}) {\n const isDot = badge === true || badge === 0;\n if (isDot) {\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -2,\n right: -2,\n width: 10,\n height: 10,\n borderRadius: 5,\n backgroundColor: dangerColor,\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n />\n );\n }\n const count = typeof badge === \"number\" ? (badge > 99 ? \"99+\" : String(badge)) : \"\";\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -6,\n right: -10,\n minWidth: 16,\n height: 16,\n borderRadius: 8,\n paddingHorizontal: 4,\n backgroundColor: dangerColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n >\n <Text style={{color: \"#FFFFFF\", fontSize: 9, fontWeight: \"700\", lineHeight: 11}}>{count}</Text>\n </Box>\n );\n}\n\n/**\n * BottomTabBar — iOS/Android bottom navigation with an elevated center FAB.\n *\n * Layout mirrors the app's working `AMTabBar`: a `row` / `space-between` bar\n * with four `flex:1` **column** slots and a content-width centre slot holding\n * the FAB. The FAB is lifted with `marginTop:-26` and ringed with a 3px\n * border so it sits above the bar plane — never absolutely positioned.\n * Presentational + controlled (router-agnostic).\n */\nexport function BottomTabBar<K extends string = string>(rawProps: IBottomTabBarProps<K>) {\n const props = useComponentDefaults<IBottomTabBarProps<K>>(\"BottomTabBar\", rawProps).mergedProps;\n const {\n items,\n value,\n onChange,\n activeColor = \"brand\",\n inactiveColor = \"text-secondary\",\n background = \"surface-card\",\n fabColor,\n showLabels = true,\n testID,\n } = props;\n /*\n * ⛔ ARABIC CLIPS WITHOUT AN EXPLICIT LINE BOX — a raw react-native <Text>\n * with a fontSize and no lineHeight gets the FONT'S natural box, and\n * NotoKufiArabic's is too short for its own ascenders. In an RTL script\n * that reads as a BAD TRANSLATION rather than as clipping: ش/س, غ/ع and\n * ة/ه differ only by marks above the baseline.\n * ⚠️ undefined in LTR, so no English layout moves.\n */\n const rtlLineHeight = useRtlLineHeight(undefined, 11);\n\n const insets = useSafeAreaInsets();\n\n // Resolve tokens → hex with the standalone resolver (the one `Icon` uses),\n // so colors apply on raw RN elements in both app and Storybook contexts.\n const activeC = resolveThemeTokenForNative(activeColor);\n const inactiveC = resolveThemeTokenForNative(inactiveColor);\n const bg = resolveThemeTokenForNative(background);\n const border = resolveThemeTokenForNative(\"surface-border\");\n const fabBg = resolveThemeTokenForNative(fabColor ?? activeColor);\n const danger = resolveThemeTokenForNative(\"danger\");\n\n return (\n <View\n testID={testID}\n style={{\n width: \"100%\",\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n minHeight: BAR_MIN_HEIGHT,\n paddingHorizontal: 20,\n paddingTop: 10,\n paddingBottom: Math.max(insets.bottom, 12),\n backgroundColor: bg,\n borderTopWidth: 1,\n borderTopColor: border,\n }}\n >\n {items.map((item: ITabBarItem<K>) => {\n const active = item.key === value;\n\n // Centre FAB — a content-width slot (NOT flex:1) so the four\n // side slots distribute evenly; the FAB is lifted in-flow.\n if (item.fab) {\n return (\n <Flex key={item.key} style={{alignItems: \"center\", justifyContent: \"center\"}}>\n <Pressable\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n hitSlop={8}\n style={({pressed}) => [\n {\n width: FAB_SIZE,\n height: FAB_SIZE,\n borderRadius: FAB_SIZE / 2,\n marginTop: -26,\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: fabBg,\n borderWidth: 3,\n borderColor: bg,\n shadowColor: fabBg,\n shadowOffset: {width: 0, height: 6},\n shadowOpacity: 0.35,\n shadowRadius: 12,\n elevation: 8,\n },\n pressed && {opacity: 0.9},\n ]}\n >\n <Icon name={item.icon as never} size={26} color=\"#FFFFFF\" />\n </Pressable>\n </Flex>\n );\n }\n\n const color = active ? activeC : inactiveC;\n const iconName = active && item.activeIcon != null ? item.activeIcon : item.icon;\n\n return (\n <Pressable\n key={item.key}\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n style={({pressed}) => [\n {\n flex: 1,\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 4,\n paddingVertical: 6,\n paddingHorizontal: 4,\n minHeight: 44,\n },\n pressed && {opacity: 0.7},\n ]}\n >\n <View style={{alignItems: \"center\", justifyContent: \"center\", position: \"relative\"}}>\n <Icon name={iconName as never} size={24} color={color} />\n {item.badge != null && item.badge !== false && (\n <Badge badge={item.badge} barBg={bg} dangerColor={danger} />\n )}\n </View>\n {showLabels && item.label != null && (\n <Text numberOfLines={1} style={{fontSize: 11, fontWeight: \"500\", color, ...(rtlLineHeight != null ? {lineHeight: rtlLineHeight} : {})}}>\n {item.label}\n </Text>\n )}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nexport default BottomTabBar;\n"],"names":["jsx","Box","Text","useComponentDefaults","useRtlLineHeight","useSafeAreaInsets","resolveThemeTokenForNative","View","Flex","Pressable","Icon","jsxs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../../../src/components/BottomTabBar/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport {Pressable, Text, View} from \"react-native\";\nimport {useSafeAreaInsets} from \"react-native-safe-area-context\";\nimport {resolveThemeTokenForNative} from \"@lmb-it/kitsconcertomobile\";\nimport useRtlLineHeight from \"../../hooks/useRtlLineHeight\";\nimport type {IBottomTabBarProps, ITabBarItem} from \"@lmb-it/kitsconcerto-types\";\nimport {Icon} from \"../../primitives\";\nimport {Box} from \"../../primitives\";\nimport Flex from \"../../layout/Flex\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n// Mirrors the app's AMTabBar geometry (App/src/components/shared/layout).\nconst BAR_MIN_HEIGHT = 60;\nconst FAB_SIZE = 56;\n\nfunction Badge({badge, barBg, dangerColor}: {badge: number | boolean; barBg: string; dangerColor: string}) {\n const isDot = badge === true || badge === 0;\n if (isDot) {\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -2,\n right: -2,\n width: 10,\n height: 10,\n borderRadius: 5,\n backgroundColor: dangerColor,\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n />\n );\n }\n const count = typeof badge === \"number\" ? (badge > 99 ? \"99+\" : String(badge)) : \"\";\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -6,\n right: -10,\n minWidth: 16,\n height: 16,\n borderRadius: 8,\n paddingHorizontal: 4,\n backgroundColor: dangerColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n >\n <Text style={{color: \"#FFFFFF\", fontSize: 9, fontWeight: \"700\", lineHeight: 11}}>{count}</Text>\n </Box>\n );\n}\n\n/**\n * BottomTabBar — iOS/Android bottom navigation with an elevated center FAB.\n *\n * Layout mirrors the app's working `AMTabBar`: a `row` / `space-between` bar\n * with four `flex:1` **column** slots and a content-width centre slot holding\n * the FAB. The FAB is lifted with `marginTop:-26` and ringed with a 3px\n * border so it sits above the bar plane — never absolutely positioned.\n * Presentational + controlled (router-agnostic).\n */\nexport function BottomTabBar<K extends string = string>(rawProps: IBottomTabBarProps<K>) {\n const props = useComponentDefaults<IBottomTabBarProps<K>>(\"BottomTabBar\", rawProps).mergedProps;\n const {\n items,\n value,\n onChange,\n activeColor = \"brand\",\n inactiveColor = \"text-secondary\",\n background = \"surface-card\",\n fabColor,\n showLabels = true,\n testID,\n } = props;\n /*\n * ⛔ ARABIC CLIPS WITHOUT AN EXPLICIT LINE BOX — a raw react-native <Text>\n * with a fontSize and no lineHeight gets the FONT'S natural box, and\n * NotoKufiArabic's is too short for its own ascenders. In an RTL script\n * that reads as a BAD TRANSLATION rather than as clipping: ش/س, غ/ع and\n * ة/ه differ only by marks above the baseline.\n * ⚠️ undefined in LTR, so no English layout moves.\n */\n const rtlLineHeight = useRtlLineHeight(undefined, 11);\n\n const insets = useSafeAreaInsets();\n\n // Resolve tokens → hex with the standalone resolver (the one `Icon` uses),\n // so colors apply on raw RN elements in both app and Storybook contexts.\n const activeC = resolveThemeTokenForNative(activeColor);\n const inactiveC = resolveThemeTokenForNative(inactiveColor);\n const bg = resolveThemeTokenForNative(background);\n const border = resolveThemeTokenForNative(\"surface-border\");\n const fabBg = resolveThemeTokenForNative(fabColor ?? activeColor);\n const danger = resolveThemeTokenForNative(\"danger\");\n\n return (\n <View\n testID={testID}\n style={{\n width: \"100%\",\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n minHeight: BAR_MIN_HEIGHT,\n paddingHorizontal: 20,\n paddingTop: 10,\n paddingBottom: Math.max(insets.bottom, 12),\n backgroundColor: bg,\n borderTopWidth: 1,\n borderTopColor: border,\n }}\n >\n {items.map((item: ITabBarItem<K>) => {\n const active = item.key === value;\n\n // Centre FAB — a content-width slot (NOT flex:1) so the four\n // side slots distribute evenly; the FAB is lifted in-flow.\n if (item.fab) {\n return (\n <Flex key={item.key} style={{alignItems: \"center\", justifyContent: \"center\"}}>\n <Pressable\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n hitSlop={8}\n style={({pressed}) => [\n {\n width: FAB_SIZE,\n height: FAB_SIZE,\n borderRadius: FAB_SIZE / 2,\n marginTop: -26,\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: fabBg,\n borderWidth: 3,\n borderColor: bg,\n shadowColor: fabBg,\n shadowOffset: {width: 0, height: 6},\n shadowOpacity: 0.35,\n shadowRadius: 12,\n elevation: 8,\n },\n pressed && {opacity: 0.9},\n ]}\n >\n <Icon name={item.icon as never} size={26} color=\"#FFFFFF\" />\n </Pressable>\n </Flex>\n );\n }\n\n const color = active ? activeC : inactiveC;\n const iconName = active && item.activeIcon != null ? item.activeIcon : item.icon;\n\n return (\n <Pressable\n key={item.key}\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n style={({pressed}) => [\n {\n flex: 1,\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 4,\n paddingVertical: 6,\n paddingHorizontal: 4,\n minHeight: 44,\n },\n pressed && {opacity: 0.7},\n ]}\n >\n <View style={{alignItems: \"center\", justifyContent: \"center\", position: \"relative\"}}>\n <Icon name={iconName as never} size={24} color={color} />\n {item.badge != null && item.badge !== false && (\n <Badge badge={item.badge} barBg={bg} dangerColor={danger} />\n )}\n </View>\n {showLabels && item.label != null && (\n <Text numberOfLines={1} style={{fontSize: 11, fontWeight: \"500\", color, ...(rtlLineHeight != null ? {lineHeight: rtlLineHeight} : {})}}>\n {item.label}\n </Text>\n )}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nexport default BottomTabBar;\n"],"names":["jsx","Box","Text","useComponentDefaults","useRtlLineHeight","useSafeAreaInsets","resolveThemeTokenForNative","View","Flex","Pressable","Icon","jsxs"],"mappings":"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"}
|
|
@@ -86,6 +86,7 @@ import Box from '../../primitives/Box/index.js';
|
|
|
86
86
|
import { Icon } from '../../primitives/Icon/index.js';
|
|
87
87
|
import Flex from '../../layout/Flex/index.js';
|
|
88
88
|
import '../../contexts/DialogContext.js';
|
|
89
|
+
import '../../contexts/PermissionsContext.js';
|
|
89
90
|
import useComponentDefaults from '../../hooks/useComponentDefaults.js';
|
|
90
91
|
|
|
91
92
|
const BAR_MIN_HEIGHT = 60;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/BottomTabBar/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport {Pressable, Text, View} from \"react-native\";\nimport {useSafeAreaInsets} from \"react-native-safe-area-context\";\nimport {resolveThemeTokenForNative} from \"@lmb-it/kitsconcertomobile\";\nimport useRtlLineHeight from \"../../hooks/useRtlLineHeight\";\nimport type {IBottomTabBarProps, ITabBarItem} from \"@lmb-it/kitsconcerto-types\";\nimport {Icon} from \"../../primitives\";\nimport {Box} from \"../../primitives\";\nimport Flex from \"../../layout/Flex\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n// Mirrors the app's AMTabBar geometry (App/src/components/shared/layout).\nconst BAR_MIN_HEIGHT = 60;\nconst FAB_SIZE = 56;\n\nfunction Badge({badge, barBg, dangerColor}: {badge: number | boolean; barBg: string; dangerColor: string}) {\n const isDot = badge === true || badge === 0;\n if (isDot) {\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -2,\n right: -2,\n width: 10,\n height: 10,\n borderRadius: 5,\n backgroundColor: dangerColor,\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n />\n );\n }\n const count = typeof badge === \"number\" ? (badge > 99 ? \"99+\" : String(badge)) : \"\";\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -6,\n right: -10,\n minWidth: 16,\n height: 16,\n borderRadius: 8,\n paddingHorizontal: 4,\n backgroundColor: dangerColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n >\n <Text style={{color: \"#FFFFFF\", fontSize: 9, fontWeight: \"700\", lineHeight: 11}}>{count}</Text>\n </Box>\n );\n}\n\n/**\n * BottomTabBar — iOS/Android bottom navigation with an elevated center FAB.\n *\n * Layout mirrors the app's working `AMTabBar`: a `row` / `space-between` bar\n * with four `flex:1` **column** slots and a content-width centre slot holding\n * the FAB. The FAB is lifted with `marginTop:-26` and ringed with a 3px\n * border so it sits above the bar plane — never absolutely positioned.\n * Presentational + controlled (router-agnostic).\n */\nexport function BottomTabBar<K extends string = string>(rawProps: IBottomTabBarProps<K>) {\n const props = useComponentDefaults<IBottomTabBarProps<K>>(\"BottomTabBar\", rawProps).mergedProps;\n const {\n items,\n value,\n onChange,\n activeColor = \"brand\",\n inactiveColor = \"text-secondary\",\n background = \"surface-card\",\n fabColor,\n showLabels = true,\n testID,\n } = props;\n /*\n * ⛔ ARABIC CLIPS WITHOUT AN EXPLICIT LINE BOX — a raw react-native <Text>\n * with a fontSize and no lineHeight gets the FONT'S natural box, and\n * NotoKufiArabic's is too short for its own ascenders. In an RTL script\n * that reads as a BAD TRANSLATION rather than as clipping: ش/س, غ/ع and\n * ة/ه differ only by marks above the baseline.\n * ⚠️ undefined in LTR, so no English layout moves.\n */\n const rtlLineHeight = useRtlLineHeight(undefined, 11);\n\n const insets = useSafeAreaInsets();\n\n // Resolve tokens → hex with the standalone resolver (the one `Icon` uses),\n // so colors apply on raw RN elements in both app and Storybook contexts.\n const activeC = resolveThemeTokenForNative(activeColor);\n const inactiveC = resolveThemeTokenForNative(inactiveColor);\n const bg = resolveThemeTokenForNative(background);\n const border = resolveThemeTokenForNative(\"surface-border\");\n const fabBg = resolveThemeTokenForNative(fabColor ?? activeColor);\n const danger = resolveThemeTokenForNative(\"danger\");\n\n return (\n <View\n testID={testID}\n style={{\n width: \"100%\",\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n minHeight: BAR_MIN_HEIGHT,\n paddingHorizontal: 20,\n paddingTop: 10,\n paddingBottom: Math.max(insets.bottom, 12),\n backgroundColor: bg,\n borderTopWidth: 1,\n borderTopColor: border,\n }}\n >\n {items.map((item: ITabBarItem<K>) => {\n const active = item.key === value;\n\n // Centre FAB — a content-width slot (NOT flex:1) so the four\n // side slots distribute evenly; the FAB is lifted in-flow.\n if (item.fab) {\n return (\n <Flex key={item.key} style={{alignItems: \"center\", justifyContent: \"center\"}}>\n <Pressable\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n hitSlop={8}\n style={({pressed}) => [\n {\n width: FAB_SIZE,\n height: FAB_SIZE,\n borderRadius: FAB_SIZE / 2,\n marginTop: -26,\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: fabBg,\n borderWidth: 3,\n borderColor: bg,\n shadowColor: fabBg,\n shadowOffset: {width: 0, height: 6},\n shadowOpacity: 0.35,\n shadowRadius: 12,\n elevation: 8,\n },\n pressed && {opacity: 0.9},\n ]}\n >\n <Icon name={item.icon as never} size={26} color=\"#FFFFFF\" />\n </Pressable>\n </Flex>\n );\n }\n\n const color = active ? activeC : inactiveC;\n const iconName = active && item.activeIcon != null ? item.activeIcon : item.icon;\n\n return (\n <Pressable\n key={item.key}\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n style={({pressed}) => [\n {\n flex: 1,\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 4,\n paddingVertical: 6,\n paddingHorizontal: 4,\n minHeight: 44,\n },\n pressed && {opacity: 0.7},\n ]}\n >\n <View style={{alignItems: \"center\", justifyContent: \"center\", position: \"relative\"}}>\n <Icon name={iconName as never} size={24} color={color} />\n {item.badge != null && item.badge !== false && (\n <Badge badge={item.badge} barBg={bg} dangerColor={danger} />\n )}\n </View>\n {showLabels && item.label != null && (\n <Text numberOfLines={1} style={{fontSize: 11, fontWeight: \"500\", color, ...(rtlLineHeight != null ? {lineHeight: rtlLineHeight} : {})}}>\n {item.label}\n </Text>\n )}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nexport default BottomTabBar;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAM,cAAA,GAAiB,EAAA;AACvB,MAAM,QAAA,GAAW,EAAA;AAEjB,SAAS,KAAA,CAAM,EAAC,KAAA,EAAO,KAAA,EAAO,aAAW,EAAkE;AACvG,EAAA,MAAM,KAAA,GAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,CAAA;AAC1C,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,uBACI,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACG,KAAA,EAAO;AAAA,UACH,QAAA,EAAU,UAAA;AAAA,UACV,GAAA,EAAK,EAAA;AAAA,UACL,KAAA,EAAO,EAAA;AAAA,UACP,KAAA,EAAO,EAAA;AAAA,UACP,MAAA,EAAQ,EAAA;AAAA,UACR,YAAA,EAAc,CAAA;AAAA,UACd,eAAA,EAAiB,WAAA;AAAA,UACjB,WAAA,EAAa,GAAA;AAAA,UACb,WAAA,EAAa,KAAA;AAAA,UACb,MAAA,EAAQ;AAAA;AACZ;AAAA,KACJ;AAAA,EAER;AACA,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,KAAU,QAAA,GAAY,QAAQ,EAAA,GAAK,KAAA,GAAQ,MAAA,CAAO,KAAK,CAAA,GAAK,EAAA;AACjF,EAAA,uBACI,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACG,KAAA,EAAO;AAAA,QACH,QAAA,EAAU,UAAA;AAAA,QACV,GAAA,EAAK,EAAA;AAAA,QACL,KAAA,EAAO,GAAA;AAAA,QACP,QAAA,EAAU,EAAA;AAAA,QACV,MAAA,EAAQ,EAAA;AAAA,QACR,YAAA,EAAc,CAAA;AAAA,QACd,iBAAA,EAAmB,CAAA;AAAA,QACnB,eAAA,EAAiB,WAAA;AAAA,QACjB,UAAA,EAAY,QAAA;AAAA,QACZ,cAAA,EAAgB,QAAA;AAAA,QAChB,WAAA,EAAa,GAAA;AAAA,QACb,WAAA,EAAa,KAAA;AAAA,QACb,MAAA,EAAQ;AAAA,OACZ;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAO,EAAC,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU,CAAA,EAAG,UAAA,EAAY,KAAA,EAAO,UAAA,EAAY,EAAA,IAAM,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA,GAC5F;AAER;AAWO,SAAS,aAAwC,QAAA,EAAiC;AACrF,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAA4C,cAAA,EAAgB,QAAQ,CAAA,CAAE,WAAA;AACpF,EAAA,MAAM;AAAA,IACF,KAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA,GAAc,OAAA;AAAA,IACd,aAAA,GAAgB,gBAAA;AAAA,IAChB,UAAA,GAAa,cAAA;AAAA,IACb,QAAA;AAAA,IACA,UAAA,GAAa,IAAA;AAAA,IACb;AAAA,GACJ,GAAI,KAAA;AASJ,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,MAAA,EAAW,EAAE,CAAA;AAEpD,EAAA,MAAM,SAAS,iBAAA,EAAkB;AAIjC,EAAA,MAAM,OAAA,GAAU,2BAA2B,WAAW,CAAA;AACtD,EAAA,MAAM,SAAA,GAAY,2BAA2B,aAAa,CAAA;AAC1D,EAAA,MAAM,EAAA,GAAK,2BAA2B,UAAU,CAAA;AAChD,EAAA,MAAM,MAAA,GAAS,2BAA2B,gBAAgB,CAAA;AAC1D,EAAA,MAAM,KAAA,GAAQ,0BAAA,CAA2B,QAAA,IAAY,WAAW,CAAA;AAChE,EAAA,MAAM,MAAA,GAAS,2BAA2B,QAAQ,CAAA;AAElD,EAAA,uBACI,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACG,MAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACH,KAAA,EAAO,MAAA;AAAA,QACP,aAAA,EAAe,KAAA;AAAA,QACf,UAAA,EAAY,QAAA;AAAA,QACZ,cAAA,EAAgB,eAAA;AAAA,QAChB,SAAA,EAAW,cAAA;AAAA,QACX,iBAAA,EAAmB,EAAA;AAAA,QACnB,UAAA,EAAY,EAAA;AAAA,QACZ,aAAA,EAAe,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,QAAQ,EAAE,CAAA;AAAA,QACzC,eAAA,EAAiB,EAAA;AAAA,QACjB,cAAA,EAAgB,CAAA;AAAA,QAChB,cAAA,EAAgB;AAAA,OACpB;AAAA,MAEC,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAyB;AACjC,QAAA,MAAM,MAAA,GAAS,KAAK,GAAA,KAAQ,KAAA;AAI5B,QAAA,IAAI,KAAK,GAAA,EAAK;AACV,UAAA,uBACI,GAAA,CAAC,QAAoB,KAAA,EAAO,EAAC,YAAY,QAAA,EAAU,cAAA,EAAgB,UAAQ,EACvE,QAAA,kBAAA,GAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cACG,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAAA,cAChC,iBAAA,EAAkB,QAAA;AAAA,cAClB,kBAAA,EAAoB,EAAC,QAAA,EAAU,MAAA,EAAM;AAAA,cACrC,OAAA,EAAS,CAAA;AAAA,cACT,KAAA,EAAO,CAAC,EAAC,OAAA,EAAO,KAAM;AAAA,gBAClB;AAAA,kBACI,KAAA,EAAO,QAAA;AAAA,kBACP,MAAA,EAAQ,QAAA;AAAA,kBACR,cAAc,QAAA,GAAW,CAAA;AAAA,kBACzB,SAAA,EAAW,GAAA;AAAA,kBACX,UAAA,EAAY,QAAA;AAAA,kBACZ,cAAA,EAAgB,QAAA;AAAA,kBAChB,eAAA,EAAiB,KAAA;AAAA,kBACjB,WAAA,EAAa,CAAA;AAAA,kBACb,WAAA,EAAa,EAAA;AAAA,kBACb,WAAA,EAAa,KAAA;AAAA,kBACb,YAAA,EAAc,EAAC,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAC;AAAA,kBAClC,aAAA,EAAe,IAAA;AAAA,kBACf,YAAA,EAAc,EAAA;AAAA,kBACd,SAAA,EAAW;AAAA,iBACf;AAAA,gBACA,OAAA,IAAW,EAAC,OAAA,EAAS,GAAA;AAAG,eAC5B;AAAA,cAEA,QAAA,kBAAA,GAAA,CAAC,QAAK,IAAA,EAAM,IAAA,CAAK,MAAe,IAAA,EAAM,EAAA,EAAI,OAAM,SAAA,EAAU;AAAA;AAAA,WAC9D,EAAA,EA3BO,KAAK,GA4BhB,CAAA;AAAA,QAER;AAEA,QAAA,MAAM,KAAA,GAAQ,SAAS,OAAA,GAAU,SAAA;AACjC,QAAA,MAAM,WAAW,MAAA,IAAU,IAAA,CAAK,cAAc,IAAA,GAAO,IAAA,CAAK,aAAa,IAAA,CAAK,IAAA;AAE5E,QAAA,uBACI,IAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YAEG,OAAA,EAAS,MAAM,QAAA,CAAS,IAAA,CAAK,GAAG,CAAA;AAAA,YAChC,iBAAA,EAAkB,QAAA;AAAA,YAClB,kBAAA,EAAoB,EAAC,QAAA,EAAU,MAAA,EAAM;AAAA,YACrC,KAAA,EAAO,CAAC,EAAC,OAAA,EAAO,KAAM;AAAA,cAClB;AAAA,gBACI,IAAA,EAAM,CAAA;AAAA,gBACN,aAAA,EAAe,QAAA;AAAA,gBACf,UAAA,EAAY,QAAA;AAAA,gBACZ,cAAA,EAAgB,QAAA;AAAA,gBAChB,GAAA,EAAK,CAAA;AAAA,gBACL,eAAA,EAAiB,CAAA;AAAA,gBACjB,iBAAA,EAAmB,CAAA;AAAA,gBACnB,SAAA,EAAW;AAAA,eACf;AAAA,cACA,OAAA,IAAW,EAAC,OAAA,EAAS,GAAA;AAAG,aAC5B;AAAA,YAEA,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,IAAA,EAAA,EAAK,OAAO,EAAC,UAAA,EAAY,UAAU,cAAA,EAAgB,QAAA,EAAU,QAAA,EAAU,UAAA,EAAU,EAC9E,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAM,QAAA,EAAmB,IAAA,EAAM,IAAI,KAAA,EAAc,CAAA;AAAA,gBACtD,IAAA,CAAK,KAAA,IAAS,IAAA,IAAQ,IAAA,CAAK,UAAU,KAAA,oBAClC,GAAA,CAAC,KAAA,EAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,EAAA,EAAI,aAAa,MAAA,EAAQ;AAAA,eAAA,EAElE,CAAA;AAAA,cACC,UAAA,IAAc,IAAA,CAAK,KAAA,IAAS,IAAA,oBACzB,GAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAe,CAAA,EAAG,KAAA,EAAO,EAAC,QAAA,EAAU,EAAA,EAAI,UAAA,EAAY,OAAO,KAAA,EAAO,GAAI,aAAA,IAAiB,IAAA,GAAO,EAAC,UAAA,EAAY,aAAA,EAAa,GAAI,EAAC,EAAE,EAChI,QAAA,EAAA,IAAA,CAAK,KAAA,EACV;AAAA;AAAA,WAAA;AAAA,UA3BC,IAAA,CAAK;AAAA,SA6Bd;AAAA,MAER,CAAC;AAAA;AAAA,GACL;AAER;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/BottomTabBar/index.native.tsx"],"sourcesContent":["import React from \"react\";\nimport {Pressable, Text, View} from \"react-native\";\nimport {useSafeAreaInsets} from \"react-native-safe-area-context\";\nimport {resolveThemeTokenForNative} from \"@lmb-it/kitsconcertomobile\";\nimport useRtlLineHeight from \"../../hooks/useRtlLineHeight\";\nimport type {IBottomTabBarProps, ITabBarItem} from \"@lmb-it/kitsconcerto-types\";\nimport {Icon} from \"../../primitives\";\nimport {Box} from \"../../primitives\";\nimport Flex from \"../../layout/Flex\";\nimport {useComponentDefaults} from \"../../hooks\";\n\n// Mirrors the app's AMTabBar geometry (App/src/components/shared/layout).\nconst BAR_MIN_HEIGHT = 60;\nconst FAB_SIZE = 56;\n\nfunction Badge({badge, barBg, dangerColor}: {badge: number | boolean; barBg: string; dangerColor: string}) {\n const isDot = badge === true || badge === 0;\n if (isDot) {\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -2,\n right: -2,\n width: 10,\n height: 10,\n borderRadius: 5,\n backgroundColor: dangerColor,\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n />\n );\n }\n const count = typeof badge === \"number\" ? (badge > 99 ? \"99+\" : String(badge)) : \"\";\n return (\n <Box\n style={{\n position: \"absolute\",\n top: -6,\n right: -10,\n minWidth: 16,\n height: 16,\n borderRadius: 8,\n paddingHorizontal: 4,\n backgroundColor: dangerColor,\n alignItems: \"center\",\n justifyContent: \"center\",\n borderWidth: 1.5,\n borderColor: barBg,\n zIndex: 10,\n }}\n >\n <Text style={{color: \"#FFFFFF\", fontSize: 9, fontWeight: \"700\", lineHeight: 11}}>{count}</Text>\n </Box>\n );\n}\n\n/**\n * BottomTabBar — iOS/Android bottom navigation with an elevated center FAB.\n *\n * Layout mirrors the app's working `AMTabBar`: a `row` / `space-between` bar\n * with four `flex:1` **column** slots and a content-width centre slot holding\n * the FAB. The FAB is lifted with `marginTop:-26` and ringed with a 3px\n * border so it sits above the bar plane — never absolutely positioned.\n * Presentational + controlled (router-agnostic).\n */\nexport function BottomTabBar<K extends string = string>(rawProps: IBottomTabBarProps<K>) {\n const props = useComponentDefaults<IBottomTabBarProps<K>>(\"BottomTabBar\", rawProps).mergedProps;\n const {\n items,\n value,\n onChange,\n activeColor = \"brand\",\n inactiveColor = \"text-secondary\",\n background = \"surface-card\",\n fabColor,\n showLabels = true,\n testID,\n } = props;\n /*\n * ⛔ ARABIC CLIPS WITHOUT AN EXPLICIT LINE BOX — a raw react-native <Text>\n * with a fontSize and no lineHeight gets the FONT'S natural box, and\n * NotoKufiArabic's is too short for its own ascenders. In an RTL script\n * that reads as a BAD TRANSLATION rather than as clipping: ش/س, غ/ع and\n * ة/ه differ only by marks above the baseline.\n * ⚠️ undefined in LTR, so no English layout moves.\n */\n const rtlLineHeight = useRtlLineHeight(undefined, 11);\n\n const insets = useSafeAreaInsets();\n\n // Resolve tokens → hex with the standalone resolver (the one `Icon` uses),\n // so colors apply on raw RN elements in both app and Storybook contexts.\n const activeC = resolveThemeTokenForNative(activeColor);\n const inactiveC = resolveThemeTokenForNative(inactiveColor);\n const bg = resolveThemeTokenForNative(background);\n const border = resolveThemeTokenForNative(\"surface-border\");\n const fabBg = resolveThemeTokenForNative(fabColor ?? activeColor);\n const danger = resolveThemeTokenForNative(\"danger\");\n\n return (\n <View\n testID={testID}\n style={{\n width: \"100%\",\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n minHeight: BAR_MIN_HEIGHT,\n paddingHorizontal: 20,\n paddingTop: 10,\n paddingBottom: Math.max(insets.bottom, 12),\n backgroundColor: bg,\n borderTopWidth: 1,\n borderTopColor: border,\n }}\n >\n {items.map((item: ITabBarItem<K>) => {\n const active = item.key === value;\n\n // Centre FAB — a content-width slot (NOT flex:1) so the four\n // side slots distribute evenly; the FAB is lifted in-flow.\n if (item.fab) {\n return (\n <Flex key={item.key} style={{alignItems: \"center\", justifyContent: \"center\"}}>\n <Pressable\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n hitSlop={8}\n style={({pressed}) => [\n {\n width: FAB_SIZE,\n height: FAB_SIZE,\n borderRadius: FAB_SIZE / 2,\n marginTop: -26,\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: fabBg,\n borderWidth: 3,\n borderColor: bg,\n shadowColor: fabBg,\n shadowOffset: {width: 0, height: 6},\n shadowOpacity: 0.35,\n shadowRadius: 12,\n elevation: 8,\n },\n pressed && {opacity: 0.9},\n ]}\n >\n <Icon name={item.icon as never} size={26} color=\"#FFFFFF\" />\n </Pressable>\n </Flex>\n );\n }\n\n const color = active ? activeC : inactiveC;\n const iconName = active && item.activeIcon != null ? item.activeIcon : item.icon;\n\n return (\n <Pressable\n key={item.key}\n onPress={() => onChange(item.key)}\n accessibilityRole=\"button\"\n accessibilityState={{selected: active}}\n style={({pressed}) => [\n {\n flex: 1,\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 4,\n paddingVertical: 6,\n paddingHorizontal: 4,\n minHeight: 44,\n },\n pressed && {opacity: 0.7},\n ]}\n >\n <View style={{alignItems: \"center\", justifyContent: \"center\", position: \"relative\"}}>\n <Icon name={iconName as never} size={24} color={color} />\n {item.badge != null && item.badge !== false && (\n <Badge badge={item.badge} barBg={bg} dangerColor={danger} />\n )}\n </View>\n {showLabels && item.label != null && (\n <Text numberOfLines={1} style={{fontSize: 11, fontWeight: \"500\", color, ...(rtlLineHeight != null ? {lineHeight: rtlLineHeight} : {})}}>\n {item.label}\n </Text>\n )}\n </Pressable>\n );\n })}\n </View>\n );\n}\n\nexport default BottomTabBar;\n"],"names":[],"mappings":"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"}
|
|
@@ -88,6 +88,7 @@ require('../../apps/mobile/src/Core/Input/Slot.cjs');
|
|
|
88
88
|
var index_native = require('../../assets/Icons/index.cjs');
|
|
89
89
|
var locale = require('../../hooks/locale.cjs');
|
|
90
90
|
require('../../contexts/DialogContext.cjs');
|
|
91
|
+
require('../../contexts/PermissionsContext.cjs');
|
|
91
92
|
var useComponentDefaults = require('../../hooks/useComponentDefaults.cjs');
|
|
92
93
|
var useSeverityColors = require('../../hooks/useSeverityColors.cjs');
|
|
93
94
|
var useThemedFont = require('../../hooks/useThemedFont.cjs');
|