UNPKG

@datadog/mobile-react-native

Version:

A client-side React Native module to interact with Datadog

113 lines (102 loc) 3.8 kB
import * as React from 'react'; const LABEL_PROPS = ['children', 'label', 'title', 'text']; const normalize = s => s.replace(/\s+/g, ' ').trim(); /** * Extracts readable text from arbitrary values commonly found in React trees. * * @param node - Any value: primitives, arrays, iterables, functions, or React elements. * @param prefer - Optional list of preferred values (e.g., title/label) to attempt first. * @returns Array of strings. */ export function __ddExtractText(node, prefer) { // If caller provided preferred values (title/label/etc.), use those first. if (Array.isArray(prefer)) { const preferred = prefer.flatMap(v => __ddExtractText(v)) // recurse so expressions/arrays work .map(normalize).filter(Boolean); if (preferred.length) { return preferred; } } // Base cases if (node == null || typeof node === 'boolean') { return []; } if (typeof node === 'string' || typeof node === 'number') { return [normalize(String(node))]; } // Arrays / iterables → flatten results (don’t concatenate yet) if (Array.isArray(node)) { return node.flatMap(x => __ddExtractText(x)).map(normalize).filter(Boolean); } if (typeof node === 'object' && Symbol.iterator in node) { return Array.from(node).flatMap(x => __ddExtractText(x)).map(normalize).filter(Boolean); } // Zero-arg render prop if (typeof node === 'function' && node.length === 0) { try { return __ddExtractText(node()); } catch { return []; } } // React elements if (/*#__PURE__*/React.isValidElement(node)) { const props = node.props ?? {}; // If the element itself has a direct label-ish prop, prefer it. for (const propKey of LABEL_PROPS) { if (propKey === 'children') { continue; // handle children below } const propValue = props[propKey]; if (propValue != null) { const got = __ddExtractText(propValue).map(normalize).filter(Boolean); if (got.length) { return got; } } } // Inspect children. Decide whether to return ONE joined label or MANY. const rawChildData = Array.isArray(props.children) ? props.children : [props.children]; const children = rawChildData.filter(c => c != null && c !== false); if (children.length === 0) { return []; } // Extract each child to a list of strings (not joined) const perChild = children.map(child => __ddExtractText(child)); // Heuristic: treat as *compound* if multiple children look like “items” // e.g., at least two direct children have a label-ish prop or yield non-empty text individually. let labeledChildCount = 0; children.forEach((child, i) => { let hasLabelProp = false; if (/*#__PURE__*/React.isValidElement(child)) { const childProps = child.props ?? {}; hasLabelProp = LABEL_PROPS.some(k => childProps?.[k] != null); } const childTextCount = perChild[i].filter(Boolean).length; if (hasLabelProp || childTextCount > 0) { labeledChildCount++; } }); const flat = perChild.flat().map(normalize).filter(Boolean); // If there are multiple *direct* labelled children, return many (compound). // Otherwise, return a single joined label. if (labeledChildCount > 1) { // De-duplicate while preserving order const seen = new Set(); const out = []; for (const str of flat) { const key = str; if (!seen.has(key)) { seen.add(key); out.push(str); } } return out; } // Not “compound”: join everything into one readable string const joined = normalize(flat.join(' ')); return joined ? [joined] : []; } return []; } //# sourceMappingURL=ddBabelUtils.js.map