({ children }: InspectorNodeProps)
| 44 | } |
| 45 | |
| 46 | export function InspectorNode({ children }: InspectorNodeProps) { |
| 47 | const { editor } = useCurrentEditor(); |
| 48 | const theming = useEmailTheming(editor); |
| 49 | const { target } = useInspector(); |
| 50 | const documentColors = useDocumentColors(editor); |
| 51 | |
| 52 | const [localAttr, setLocalAttr] = React.useState< |
| 53 | FocusedNode['nodeAttrs'] | null |
| 54 | >(null); |
| 55 | |
| 56 | const focusedNode = |
| 57 | typeof target === 'object' && target.nodeType !== 'body' ? target : null; |
| 58 | |
| 59 | React.useEffect(() => { |
| 60 | if (focusedNode) { |
| 61 | setLocalAttr(focusedNode.nodeAttrs); |
| 62 | } |
| 63 | }, [focusedNode]); |
| 64 | |
| 65 | if (!editor || !theming || !focusedNode) { |
| 66 | return null; |
| 67 | } |
| 68 | |
| 69 | const attrs = localAttr ?? focusedNode.nodeAttrs; |
| 70 | const inlineStyles = inlineCssToJs(attrs.style || ''); |
| 71 | |
| 72 | const css = stylesToCss(theming.styles, theming.theme); |
| 73 | const themeDefaults = resolveThemeDefaults( |
| 74 | focusedNode.nodeType, |
| 75 | attrs as Record<string, unknown>, |
| 76 | css, |
| 77 | ); |
| 78 | |
| 79 | const mergedStyles: Record<string, string | number | undefined> = { |
| 80 | ...themeDefaults, |
| 81 | ...inlineStyles, |
| 82 | }; |
| 83 | |
| 84 | const getStyle = (prop: KnownCssProperties) => { |
| 85 | const value = mergedStyles[prop]; |
| 86 | // Strip the trailing CSS unit only for numeric properties so that |
| 87 | // numeric inputs receive a parseable number. Non-numeric properties |
| 88 | // (colors, gradients, etc.) are returned verbatim — stripping `%`/`px` |
| 89 | // globally would corrupt values like `hsl(200, 50%, 40%)`. |
| 90 | const isNumericProperty = Boolean(SUPPORTED_CSS_PROPERTIES[prop]?.unit); |
| 91 | if (isNumericProperty && typeof value === 'string') { |
| 92 | return value.replace(/(px|%)$/, ''); |
| 93 | } |
| 94 | return value; |
| 95 | }; |
| 96 | |
| 97 | const setStyle = (prop: KnownCssProperties, value: string | number) => { |
| 98 | customUpdateStyles( |
| 99 | { |
| 100 | editor, |
| 101 | nodePos: focusedNode.nodePos, |
| 102 | prop, |
| 103 | newValue: value, |
nothing calls this directly
no test coverage detected