{"version":3,"file":"YogaManager-Cze4Apic.cjs","names":[],"sources":["../src/util/parseFlexValue.ts","../src/util/applyReactPropsToYoga.ts","../src/YogaManager.ts"],"sourcesContent":["import type { AutoDimensionValue } from '../types';\n\ntype FlexConfig = {\n  grow: number;\n  shrink: number;\n  basis: AutoDimensionValue | string;\n};\n\n// Cache for parsed flex values\nconst flexCache = new Map<string | number, FlexConfig>();\n\nexport function parseFlexValue(\n  value: string | number,\n  expandToAutoFlexBasis = false,\n): FlexConfig | null {\n  // Check cache first for string values to prevent parsing again\n  const cached = flexCache.get(value);\n\n  if (cached) {\n    return cached;\n  }\n\n  let flexConfig: {\n    grow: number;\n    shrink: number;\n    basis: AutoDimensionValue | string;\n  };\n\n  if (typeof value === 'number') {\n    flexConfig = {\n      grow: value,\n      shrink: 1,\n      basis: expandToAutoFlexBasis ? 'auto' : '0%',\n    };\n  } else {\n    // Trim whitespace and filter out empty parts\n    const parts = value\n      .trim()\n      .split(/\\s+/)\n      .filter((part) => part.length > 0);\n\n    // Return null for empty input\n    if (parts.length === 0) {\n      return null;\n    }\n\n    const [grow, shrink, basis] = parts;\n\n    // Helper function to check if a string is a valid number (including decimals and negatives)\n    const isValidNumber = (str: string): boolean => {\n      return /^-?(\\d+\\.?\\d*|\\d*\\.\\d+)([eE][+-]?\\d+)?$/.test(str.trim());\n    };\n\n    // https://developer.mozilla.org/en-US/docs/Web/CSS/flex\n    if (parts.length === 3 && grow != null && shrink != null && basis != null) {\n      flexConfig = {\n        grow: Number.parseFloat(grow),\n        shrink: Number.parseFloat(shrink),\n        basis,\n      };\n    } else if (parts.length === 2 && grow != null && shrink != null) {\n      // For two values, if the second value is a pure number (not \"0\"), treat as grow/shrink\n      // If it's \"0\" or has units, treat as grow/basis\n      if (isValidNumber(shrink) && shrink !== '0') {\n        flexConfig = {\n          grow: Number.parseFloat(grow),\n          shrink: Number.parseFloat(shrink),\n          basis: 0,\n        };\n      } else {\n        flexConfig = {\n          grow: Number.parseFloat(grow),\n          shrink: 1,\n          basis: shrink,\n        };\n      }\n    } else if (parts.length === 1 && grow != null) {\n      if (isValidNumber(grow)) {\n        flexConfig = {\n          grow: Number.parseFloat(grow),\n          shrink: 1,\n          basis: expandToAutoFlexBasis ? 'auto' : '0%',\n        };\n      } else if (grow === 'none') {\n        flexConfig = { grow: 0, shrink: 0, basis: 'auto' };\n      } else {\n        flexConfig = { grow: 1, shrink: 1, basis: grow };\n      }\n    } else {\n      return null;\n    }\n  }\n\n  // Cache the parsed result\n  flexCache.set(value, flexConfig);\n\n  return flexConfig;\n}\n","import type {\n  Align,\n  Display,\n  Justify,\n  Node,\n  PositionType,\n  Wrap,\n  FlexDirection as YogaFlexDirection,\n} from 'yoga-layout';\nimport type { Yoga } from 'yoga-layout/load';\n\nimport type { LightningViewElementStyle } from '@plextv/react-lightning';\n\nimport type { YogaOptions } from '../types';\nimport type { AutoDimensionValue, Transform } from '../types/FlexStyles';\nimport type { ManagerNode } from '../types/ManagerNode';\nimport type { FlexProps } from './isFlexStyleProp';\nimport { isFlexStyleProp } from './isFlexStyleProp';\nimport { parseFlexValue } from './parseFlexValue';\n\nfunction mapDisplay(yoga: Yoga, value?: 'flex' | 'none'): Display {\n  switch (value) {\n    case 'none':\n      return yoga.DISPLAY_NONE;\n    default:\n      return yoga.DISPLAY_FLEX;\n  }\n}\n\nfunction mapDirection(yoga: Yoga, value?: number | string): YogaFlexDirection {\n  switch (value) {\n    case 'column-reverse':\n      return yoga.FLEX_DIRECTION_COLUMN_REVERSE;\n    case 'column':\n      return yoga.FLEX_DIRECTION_COLUMN;\n    case 'row-reverse':\n      return yoga.FLEX_DIRECTION_ROW_REVERSE;\n    default:\n      return yoga.FLEX_DIRECTION_ROW;\n  }\n}\n\nfunction mapAlignItems(yoga: Yoga, value?: number | string): Align {\n  switch (value) {\n    case 'flex-start':\n      return yoga.ALIGN_FLEX_START;\n    case 'flex-end':\n      return yoga.ALIGN_FLEX_END;\n    case 'center':\n      return yoga.ALIGN_CENTER;\n    case 'baseline':\n      return yoga.ALIGN_BASELINE;\n    default:\n      return yoga.ALIGN_STRETCH;\n  }\n}\n\nfunction mapAlignContent(yoga: Yoga, value?: number | string): Align {\n  switch (value) {\n    case 'space-around':\n      return yoga.ALIGN_SPACE_AROUND;\n    case 'space-between':\n    case 'space-evenly':\n      return yoga.ALIGN_SPACE_BETWEEN;\n    case 'center':\n      return yoga.ALIGN_CENTER;\n    case 'flex-end':\n      return yoga.ALIGN_FLEX_END;\n    case 'stretch':\n      return yoga.ALIGN_STRETCH;\n    default:\n      return yoga.ALIGN_FLEX_START;\n  }\n}\n\nfunction mapWrap(yoga: Yoga, value?: number | string): Wrap {\n  switch (value) {\n    case 'wrap':\n      return yoga.WRAP_WRAP;\n    case 'wrap-reverse':\n      return yoga.WRAP_WRAP_REVERSE;\n    default:\n      return yoga.WRAP_NO_WRAP;\n  }\n}\n\nfunction mapJustify(yoga: Yoga, value?: number | string): Justify {\n  switch (value) {\n    case 'center':\n      return yoga.JUSTIFY_CENTER;\n    case 'flex-end':\n      return yoga.JUSTIFY_FLEX_END;\n    case 'space-around':\n      return yoga.JUSTIFY_SPACE_AROUND;\n    case 'space-between':\n      return yoga.JUSTIFY_SPACE_BETWEEN;\n    case 'space-evenly':\n      return yoga.JUSTIFY_SPACE_EVENLY;\n    default:\n      return yoga.JUSTIFY_FLEX_START;\n  }\n}\n\nfunction mapPosition(yoga: Yoga, value?: number | string): PositionType {\n  switch (value) {\n    case 'absolute':\n    case 'fixed':\n      return yoga.POSITION_TYPE_ABSOLUTE;\n    case 'static':\n      return yoga.POSITION_TYPE_STATIC;\n    default:\n      return yoga.POSITION_TYPE_RELATIVE;\n  }\n}\n\nfunction formatSizeValue<T extends keyof LightningViewElementStyle>(\n  value?: string | number | undefined,\n): LightningViewElementStyle[T] {\n  if (value === 'none' || value === 'auto') {\n    return undefined;\n  }\n\n  return value as LightningViewElementStyle[T];\n}\n\nfunction applyFlexBasis(node: Node, value?: AutoDimensionValue | string) {\n  if (value == null) {\n    return;\n  }\n\n  if (typeof value === 'string') {\n    if (value === 'auto') {\n      node.setFlexBasisAuto();\n    } else if (value.endsWith('%')) {\n      node.setFlexBasisPercent(Number.parseFloat(value));\n    } else {\n      node.setFlexBasis(Number.parseFloat(value));\n    }\n  } else if (typeof value === 'number') {\n    node.setFlexBasis(value);\n  }\n}\n\nfunction applyFlex(node: Node, value?: string | number, expandToAutoFlexBasis = false) {\n  if (value == null) {\n    return;\n  }\n\n  const flexConfig = parseFlexValue(value, expandToAutoFlexBasis);\n\n  if (flexConfig) {\n    node.setFlexGrow(flexConfig.grow);\n    node.setFlexShrink(flexConfig.shrink);\n    applyFlexBasis(node, flexConfig.basis);\n  }\n}\n\nexport default function applyReactPropsToYoga(\n  yoga: Yoga,\n  config: YogaOptions,\n  managerNode: ManagerNode,\n  style: Partial<LightningViewElementStyle>,\n): void {\n  // `for...in` instead of `Object.entries(style)` to avoid the per-call\n  // array allocation. This function runs on every applyStyle dispatch,\n  // which during a UI update can be hundreds of times per frame.\n  for (const prop in style) {\n    if (isFlexStyleProp(prop)) {\n      const value = style[prop];\n\n      if (managerNode.props[prop] !== value) {\n        managerNode.props[prop] = value;\n\n        applyFlexPropToYoga(\n          yoga,\n          config,\n          managerNode.node,\n          prop,\n          value as LightningViewElementStyle[typeof prop],\n        );\n      }\n    }\n  }\n}\n\nexport function applyFlexPropToYoga<K extends FlexProps>(\n  yoga: Yoga,\n  config: YogaOptions,\n  node: Node,\n  key: K,\n  styleValue: LightningViewElementStyle[K],\n): boolean {\n  if (styleValue == null) {\n    return false;\n  }\n\n  try {\n    const value = styleValue as Exclude<LightningViewElementStyle[K], Transform>;\n\n    switch (key) {\n      case 'display':\n        node.setDisplay(mapDisplay(yoga, value as LightningViewElementStyle['display']));\n        return true;\n      case 'w':\n        node.setWidth(value as LightningViewElementStyle['w']);\n        return true;\n      case 'minWidth':\n        node.setMinWidth(value as LightningViewElementStyle['minWidth']);\n        return true;\n      case 'maxWidth':\n        node.setMaxWidth(formatSizeValue<'maxWidth'>(value));\n        return true;\n      case 'h':\n        node.setHeight(value as LightningViewElementStyle['h']);\n        return true;\n      case 'minHeight':\n        node.setMinHeight(value as LightningViewElementStyle['minHeight']);\n        return true;\n      case 'maxHeight':\n        node.setMaxHeight(formatSizeValue<'maxHeight'>(value));\n        return true;\n      case 'aspectRatio':\n        node.setAspectRatio(value as LightningViewElementStyle['aspectRatio']);\n        return true;\n      case 'margin':\n        node.setMargin(yoga.EDGE_ALL, value as LightningViewElementStyle['margin']);\n        return true;\n      case 'marginBottom':\n        node.setMargin(yoga.EDGE_BOTTOM, value as LightningViewElementStyle['marginBottom']);\n        return true;\n      case 'marginEnd':\n        node.setMargin(yoga.EDGE_END, value as LightningViewElementStyle['marginEnd']);\n        return true;\n      case 'marginLeft':\n        node.setMargin(yoga.EDGE_LEFT, value as LightningViewElementStyle['marginLeft']);\n        return true;\n      case 'marginRight':\n        node.setMargin(yoga.EDGE_RIGHT, value as LightningViewElementStyle['marginRight']);\n        return true;\n      case 'marginStart':\n        node.setMargin(yoga.EDGE_START, value as LightningViewElementStyle['marginStart']);\n        return true;\n      case 'marginTop':\n        node.setMargin(yoga.EDGE_TOP, value as LightningViewElementStyle['marginTop']);\n        return true;\n      case 'marginHorizontal':\n      case 'marginInline':\n        node.setMargin(yoga.EDGE_HORIZONTAL, value as LightningViewElementStyle['marginInline']);\n        return true;\n      case 'marginVertical':\n      case 'marginBlock':\n        node.setMargin(yoga.EDGE_VERTICAL, value as LightningViewElementStyle['marginBlock']);\n        return true;\n      case 'padding':\n        node.setPadding(yoga.EDGE_ALL, value as LightningViewElementStyle['padding']);\n        return true;\n      case 'paddingBottom':\n        node.setPadding(yoga.EDGE_BOTTOM, value as LightningViewElementStyle['paddingBottom']);\n        return true;\n      case 'paddingEnd':\n        node.setPadding(yoga.EDGE_END, value as LightningViewElementStyle['paddingEnd']);\n        return true;\n      case 'paddingLeft':\n        node.setPadding(yoga.EDGE_LEFT, value as LightningViewElementStyle['paddingLeft']);\n        return true;\n      case 'paddingRight':\n        node.setPadding(yoga.EDGE_RIGHT, value as LightningViewElementStyle['paddingRight']);\n        return true;\n      case 'paddingStart':\n        node.setPadding(yoga.EDGE_START, value as LightningViewElementStyle['paddingStart']);\n        return true;\n      case 'paddingTop':\n        node.setPadding(yoga.EDGE_TOP, value as LightningViewElementStyle['paddingTop']);\n        return true;\n      case 'paddingHorizontal':\n      case 'paddingInline':\n        node.setPadding(yoga.EDGE_HORIZONTAL, value as LightningViewElementStyle['paddingInline']);\n        return true;\n      case 'paddingVertical':\n      case 'paddingBlock':\n        node.setPadding(yoga.EDGE_VERTICAL, value as LightningViewElementStyle['paddingBlock']);\n        return true;\n      case 'flex':\n        applyFlex(node, value, config.expandToAutoFlexBasis);\n        return true;\n      case 'flexDirection':\n        node.setFlexDirection(mapDirection(yoga, value));\n        return true;\n      case 'alignContent':\n        node.setAlignContent(mapAlignContent(yoga, value));\n        return true;\n      case 'alignItems':\n        node.setAlignItems(mapAlignItems(yoga, value));\n        return true;\n      case 'alignSelf':\n        node.setAlignSelf(mapAlignItems(yoga, value));\n        return true;\n      case 'justifyContent':\n        node.setJustifyContent(mapJustify(yoga, value));\n        return true;\n      case 'flexWrap':\n        node.setFlexWrap(mapWrap(yoga, value));\n        return true;\n      case 'flexBasis':\n        applyFlexBasis(node, value as LightningViewElementStyle['flexBasis']);\n        return true;\n      case 'flexGrow':\n        node.setFlexGrow((value as LightningViewElementStyle['flexGrow']) ?? 1);\n        return true;\n      case 'flexShrink':\n        node.setFlexShrink((value as LightningViewElementStyle['flexShrink']) ?? 0);\n        return true;\n      case 'gap':\n        node.setGap(yoga.GUTTER_ALL, (value as LightningViewElementStyle['gap']) ?? 0);\n        return true;\n      case 'columnGap':\n        node.setGap(yoga.GUTTER_COLUMN, (value as LightningViewElementStyle['columnGap']) ?? 0);\n        return true;\n      case 'rowGap':\n        node.setGap(yoga.GUTTER_ROW, (value as LightningViewElementStyle['rowGap']) ?? 0);\n        return true;\n      case 'position':\n        node.setPositionType(mapPosition(yoga, value));\n        return true;\n      case 'right':\n        node.setPosition(yoga.EDGE_RIGHT, (value as LightningViewElementStyle['right']) ?? 0);\n        return true;\n      case 'bottom':\n        node.setPosition(yoga.EDGE_BOTTOM, (value as LightningViewElementStyle['bottom']) ?? 0);\n        return true;\n      case 'left':\n        node.setPosition(yoga.EDGE_LEFT, (value as LightningViewElementStyle['left']) ?? 0);\n        return true;\n      case 'top':\n        node.setPosition(yoga.EDGE_TOP, (value as LightningViewElementStyle['top']) ?? 0);\n        return true;\n    }\n  } catch (err) {\n    console.error(err);\n  }\n\n  return false;\n}\n","import { EventEmitter } from 'tseep';\nimport { type Config, loadYoga, type Yoga } from 'yoga-layout/load';\n\nimport type { LightningElementStyle, Rect } from '@plextv/react-lightning';\n\nimport type { ManagerNode } from './types/ManagerNode';\nimport type { YogaOptions } from './types/YogaOptions';\nimport applyReactPropsToYoga, { applyFlexPropToYoga } from './util/applyReactPropsToYoga';\nimport { SimpleDataView } from './util/SimpleDataView';\n\nexport type BatchedUpdate = Record<number, Partial<Rect>>;\n\nexport type YogaManagerEvents = {\n  // Updates are sent in an array. This is because when working with web\n  // workers, it's more efficient to transfer an array instead of serializing\n  // values and sending them over postMessage. The first 32 unsigned bits of the\n  // array are reserved for the number of elements being updated. The rest of the\n  // array contains the updates for each element. The data structure is as follows:\n  //   uint32 - The element ID of the element being updated\n  //   int16 - The x coordinate of the element\n  //   int16 - The y coordinate of the element\n  //   int16 - The width of the element\n  //   int16 - The height of the element\n  render: (updates: ArrayBuffer) => void;\n};\n\n// elementId + x + y + width + height, as per spec above\nconst APPROX_SIZEOF_UPDATE = 4 + 2 + 2 + 2 + 2;\n// 10KB, should be enough for most updates. If it's bigger than this, we'll chunk the updates\nconst MAX_SIZEOF_UPDATE = 1024 * 10;\n\nexport class YogaManager {\n  private _elementMap: Map<number, ManagerNode> = new Map();\n  private _hiddenElements: Set<number> = new Set();\n  private _independentRoots: Set<ManagerNode> = new Set();\n  private _yoga?: Yoga;\n  private _config?: Config;\n  private _initialized = false;\n  private _isRenderQueued = false;\n  private _yogaOptions: Required<YogaOptions> = {\n    useWebDefaults: false,\n    errata: 'none',\n    processHiddenNodes: false,\n    useWebWorker: false,\n    expandToAutoFlexBasis: false,\n  };\n  private _eventEmitter: EventEmitter<YogaManagerEvents> = new EventEmitter();\n  private _dataView: SimpleDataView;\n\n  public on: EventEmitter<YogaManagerEvents>['on'] = this._eventEmitter.on.bind(this._eventEmitter);\n  public off: EventEmitter<YogaManagerEvents>['off'] = this._eventEmitter.off.bind(\n    this._eventEmitter,\n  );\n\n  public get initialized(): boolean {\n    return this._initialized;\n  }\n\n  public constructor() {\n    this._dataView = new SimpleDataView(MAX_SIZEOF_UPDATE, true, this._flushArrayBuffer);\n  }\n\n  public async init(yogaOptions?: YogaOptions): Promise<void> {\n    Object.assign(this._yogaOptions, yogaOptions);\n\n    this._yoga = await loadYoga();\n    this._config = this._yoga.Config.create();\n    this._config.setUseWebDefaults(this._yogaOptions.useWebDefaults);\n\n    switch (this._yogaOptions.errata) {\n      case 'all':\n        this._config.setErrata(this._yoga.ERRATA_ALL);\n        break;\n      case 'classic':\n        this._config.setErrata(this._yoga.ERRATA_CLASSIC);\n        break;\n      case 'stretch-flex-basis':\n        this._config.setErrata(this._yoga.ERRATA_STRETCH_FLEX_BASIS);\n        break;\n      case 'absolute-percent-against-inner':\n        this._config.setErrata(this._yoga.ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE);\n        break;\n      case 'absolute-position-without-insets':\n        this._config.setErrata(this._yoga.ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING);\n        break;\n      default:\n        this._config.setErrata(this._yoga.ERRATA_NONE);\n        break;\n    }\n\n    this._initialized = true;\n  }\n\n  public addNode(elementId: number): ManagerNode {\n    if (this._elementMap.has(elementId)) {\n      // oxlint-disable-next-line typescript/no-non-null-assertion -- Already checked\n      return this._elementMap.get(elementId)!;\n    }\n\n    const node = this._createNode(elementId);\n\n    this._elementMap.set(elementId, node);\n\n    return node;\n  }\n\n  public removeNode(elementId: number): void {\n    const yogaNode = this._elementMap.get(elementId);\n\n    if (yogaNode) {\n      yogaNode.node.free();\n\n      // Remove the node from its parent's children array\n      if (yogaNode.parent) {\n        const index = yogaNode.parent.children.indexOf(yogaNode);\n\n        if (index !== -1) {\n          yogaNode.parent.children.splice(index, 1);\n        }\n      }\n\n      this._elementMap.delete(elementId);\n    }\n  }\n\n  public addChildNode(parentId: number, childId: number, index?: number): void {\n    const parentYogaNode = this._elementMap.get(parentId);\n    const childYogaNode = this._elementMap.get(childId);\n\n    if (!parentYogaNode || !childYogaNode) {\n      throw new Error(`Parent or child node not found for IDs ${parentId} and ${childId}.`);\n    }\n\n    index ??= childYogaNode.children.length;\n\n    parentYogaNode.node.insertChild(childYogaNode.node, index);\n    parentYogaNode.children.splice(index, 0, childYogaNode);\n    childYogaNode.parent = parentYogaNode;\n  }\n\n  public detachChildNode(parentId: number, childId: number): void {\n    const parentYogaNode = this._elementMap.get(parentId);\n    const childYogaNode = this._elementMap.get(childId);\n\n    if (!parentYogaNode || !childYogaNode) {\n      return;\n    }\n\n    const idx = parentYogaNode.children.indexOf(childYogaNode);\n\n    if (idx === -1) {\n      return;\n    }\n\n    parentYogaNode.node.removeChild(childYogaNode.node);\n    parentYogaNode.children.splice(idx, 1);\n    childYogaNode.parent = undefined;\n  }\n\n  public addIndependentRoot(elementId: number): void {\n    const node = this._elementMap.get(elementId);\n\n    if (node) {\n      this._independentRoots.add(node);\n    }\n  }\n\n  public removeIndependentRoot(elementId: number): void {\n    const node = this._elementMap.get(elementId);\n\n    if (node) {\n      this._independentRoots.delete(node);\n    }\n  }\n\n  public queueRender(_elementId: number, force = false): void {\n    if (!this._initialized || !this._yoga) {\n      throw new Error('Yoga is not initialized! Did you call `init()`?');\n    }\n\n    if (this._isRenderQueued) {\n      return;\n    }\n\n    this._isRenderQueued = true;\n\n    // Microtask runs AFTER the current synchronous batch of style/node\n    // ops (arriving from postMessage handlers); setTimeout's 1ms+ minimum\n    // would fragment a batch into many render passes.\n    queueMicrotask(() => {\n      this._isRenderQueued = false;\n\n      if (this._independentRoots.size === 0) {\n        return;\n      }\n\n      this._initializeArrayBuffer();\n\n      for (const independentRoot of this._independentRoots) {\n        // undefined available size → yoga uses the root's own w/h (or\n        // shrink-to-fit). Passing 1920×1080 would stretch any unset axis\n        // and break measurement-driven roots like VirtualList cells.\n        independentRoot.node.calculateLayout(\n          undefined,\n          undefined,\n          // oxlint-disable-next-line typescript/no-non-null-assertion -- Already checked this._yoga above\n          this._yoga!.DIRECTION_LTR,\n        );\n        this._getUpdatedStyles(independentRoot, force);\n      }\n\n      this._flushArrayBuffer(this._dataView.buffer);\n    });\n  }\n\n  public applyStyles(\n    styles: Record<number, Partial<LightningElementStyle>>,\n    skipRender = false,\n  ): void {\n    if (!this._initialized) {\n      throw new Error('Yoga was not initialized! Did you call `init()`?');\n    }\n\n    // `for...in` skips the [key, value] tuple allocation of Object.entries —\n    // this is a hot path on every flushBoth/applyStyles message.\n    for (const elementId in styles) {\n      // oxlint-disable-next-line typescript/no-non-null-assertion -- key from for..in iteration of own props\n      this.applyStyle(+elementId, styles[elementId as unknown as number]!, skipRender);\n    }\n  }\n\n  public applyStyle(\n    elementId: number,\n    style: Partial<LightningElementStyle> | null,\n    skipRender = false,\n  ): void {\n    if (!style) {\n      return;\n    }\n\n    if (!this._initialized || !this._yoga || !this._config) {\n      throw new Error('Yoga was not initialized! Did you call `init()`?');\n    }\n\n    const yogaNode = this._elementMap.get(elementId);\n\n    if (!yogaNode) {\n      console.warn(`Yoga node with ID ${elementId} not found.`);\n\n      return;\n    }\n\n    applyReactPropsToYoga(this._yoga, this._yogaOptions, yogaNode, style);\n\n    if (style.transform) {\n      const { x, y, transform } = style;\n\n      // Apply transforms after all the styles are applied\n      if (transform) {\n        const { translateX, translateY } = transform;\n\n        if (translateX != null) {\n          const left = x ?? 0;\n\n          applyFlexPropToYoga(\n            this._yoga,\n            this._yogaOptions,\n            yogaNode.node,\n            'left',\n            left + translateX,\n          );\n        }\n\n        if (translateY != null) {\n          const top = y ?? 0;\n\n          applyFlexPropToYoga(\n            this._yoga,\n            this._yogaOptions,\n            yogaNode.node,\n            'top',\n            top + translateY,\n          );\n        }\n      }\n    }\n\n    if (!skipRender) {\n      this.queueRender(elementId);\n    }\n  }\n\n  private _flushArrayBuffer(buffer: ArrayBuffer) {\n    // Emit the current buffer\n    this._eventEmitter.emit('render', buffer);\n    this._initializeArrayBuffer();\n  }\n\n  private _initializeArrayBuffer() {\n    this._dataView.reset();\n  }\n\n  private _createNode(elementId: number): ManagerNode {\n    if (!this._initialized || !this._yoga || !this._config) {\n      throw new Error('Yoga was not initialized! Did you call `init()`?');\n    }\n\n    const node = this._yoga.Node.create(this._config);\n    const yogaNode = {\n      id: elementId,\n      node,\n      children: [],\n      props: {},\n    };\n\n    this._elementMap.set(elementId, yogaNode);\n\n    return yogaNode;\n  }\n\n  // Recursion is unconditional — yoga's hasNewLayout is per-node, so a\n  // child's layout can change even when the parent's didn't (absolute\n  // children, just-attached subtrees from _reattachChildren).\n  private _getUpdatedStyles(yogaNode: ManagerNode, force = false) {\n    const skipHiddenNode =\n      !this._yogaOptions.processHiddenNodes && this._hiddenElements.has(yogaNode.id);\n\n    if (!skipHiddenNode && (force || yogaNode.node.hasNewLayout())) {\n      if (!this._dataView.hasSpace(APPROX_SIZEOF_UPDATE)) {\n        this._flushArrayBuffer(this._dataView.buffer);\n      }\n\n      // Individual getters instead of getComputedLayout() — that allocates\n      // a {left, top, width, height} object per node, and we recurse the\n      // entire yoga tree every layout pass.\n      const node = yogaNode.node;\n\n      // Direct DataView writes — hasSpace above already validated the full\n      // 12-byte run, so per-call overflow checks are pure overhead here.\n      const view = this._dataView.dataView;\n      const offset = this._dataView.offset;\n\n      view.setUint32(offset, yogaNode.id, true);\n      view.setInt16(offset + 4, node.getComputedLeft(), true);\n      view.setInt16(offset + 6, node.getComputedTop(), true);\n      view.setInt16(offset + 8, node.getComputedWidth(), true);\n      view.setInt16(offset + 10, node.getComputedHeight(), true);\n      this._dataView.advance(APPROX_SIZEOF_UPDATE);\n\n      node.markLayoutSeen();\n    }\n\n    const children = yogaNode.children;\n\n    for (let i = 0, len = children.length; i < len; i++) {\n      // oxlint-disable-next-line typescript/no-non-null-assertion -- length-bounded\n      this._getUpdatedStyles(children[i]!, force);\n    }\n  }\n}\n"],"mappings":"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"}