@dialpad/dialtone 9.177.2 → 9.178.0

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.
Files changed (142) hide show
  1. package/dist/css/dialtone-default-theme.css +75 -0
  2. package/dist/css/dialtone-default-theme.min.css +1 -1
  3. package/dist/css/dialtone.css +75 -0
  4. package/dist/css/dialtone.min.css +1 -1
  5. package/dist/css/tokens-docs.json +1 -1
  6. package/dist/tokens/doc.json +112080 -112080
  7. package/dist/vue3/{attachment_carousel-BWzRsDBY.cjs → attachment_carousel-BHxR7A76.cjs} +1 -1
  8. package/dist/vue3/{attachment_carousel-BWzRsDBY.cjs.map → attachment_carousel-BHxR7A76.cjs.map} +1 -1
  9. package/dist/vue3/{attachment_carousel-Xub5CrN3.js → attachment_carousel-CouFqFMw.js} +1 -1
  10. package/dist/vue3/{attachment_carousel-Xub5CrN3.js.map → attachment_carousel-CouFqFMw.js.map} +1 -1
  11. package/dist/vue3/component-documentation.json +1 -1
  12. package/dist/vue3/components/combobox_with_popover/combobox_with_popover.vue.d.ts +2 -0
  13. package/dist/vue3/components/combobox_with_popover/combobox_with_popover.vue.d.ts.map +1 -1
  14. package/dist/vue3/components/resizable/composables/computeLayout.d.ts +35 -0
  15. package/dist/vue3/components/resizable/composables/computeLayout.d.ts.map +1 -0
  16. package/dist/vue3/components/resizable/composables/constraintResolver.d.ts +22 -0
  17. package/dist/vue3/components/resizable/composables/constraintResolver.d.ts.map +1 -0
  18. package/dist/vue3/components/resizable/composables/index.d.ts +16 -0
  19. package/dist/vue3/components/resizable/composables/index.d.ts.map +1 -0
  20. package/dist/vue3/components/resizable/composables/useResizableAnnouncements.d.ts +6 -0
  21. package/dist/vue3/components/resizable/composables/useResizableAnnouncements.d.ts.map +1 -0
  22. package/dist/vue3/components/resizable/composables/useResizableCalculations.d.ts +14 -0
  23. package/dist/vue3/components/resizable/composables/useResizableCalculations.d.ts.map +1 -0
  24. package/dist/vue3/components/resizable/composables/useResizableDrag.d.ts +42 -0
  25. package/dist/vue3/components/resizable/composables/useResizableDrag.d.ts.map +1 -0
  26. package/dist/vue3/components/resizable/composables/useResizableGroup.d.ts +25 -0
  27. package/dist/vue3/components/resizable/composables/useResizableGroup.d.ts.map +1 -0
  28. package/dist/vue3/components/resizable/composables/useResizableKeyboard.d.ts +41 -0
  29. package/dist/vue3/components/resizable/composables/useResizableKeyboard.d.ts.map +1 -0
  30. package/dist/vue3/components/resizable/composables/useResizableOffset.d.ts +15 -0
  31. package/dist/vue3/components/resizable/composables/useResizableOffset.d.ts.map +1 -0
  32. package/dist/vue3/components/resizable/composables/useResizablePanelControls.d.ts +46 -0
  33. package/dist/vue3/components/resizable/composables/useResizablePanelControls.d.ts.map +1 -0
  34. package/dist/vue3/components/resizable/composables/useResizablePanelState.d.ts +9 -0
  35. package/dist/vue3/components/resizable/composables/useResizablePanelState.d.ts.map +1 -0
  36. package/dist/vue3/components/resizable/composables/useResizableStorage.d.ts +12 -0
  37. package/dist/vue3/components/resizable/composables/useResizableStorage.d.ts.map +1 -0
  38. package/dist/vue3/components/resizable/index.d.ts +6 -0
  39. package/dist/vue3/components/resizable/index.d.ts.map +1 -0
  40. package/dist/vue3/components/resizable/resizable.vue.d.ts +69 -0
  41. package/dist/vue3/components/resizable/resizable.vue.d.ts.map +1 -0
  42. package/dist/vue3/components/resizable/resizable_constants.d.ts +103 -0
  43. package/dist/vue3/components/resizable/resizable_constants.d.ts.map +1 -0
  44. package/dist/vue3/components/resizable/resizable_handle.vue.d.ts +22 -0
  45. package/dist/vue3/components/resizable/resizable_handle.vue.d.ts.map +1 -0
  46. package/dist/vue3/components/resizable/resizable_panel.vue.d.ts +44 -0
  47. package/dist/vue3/components/resizable/resizable_panel.vue.d.ts.map +1 -0
  48. package/dist/vue3/components/resizable/resizable_utils.d.ts +15 -0
  49. package/dist/vue3/components/resizable/resizable_utils.d.ts.map +1 -0
  50. package/dist/vue3/components/rich_text_editor/rich_text_editor.vue.d.ts +2 -0
  51. package/dist/vue3/components/rich_text_editor/rich_text_editor.vue.d.ts.map +1 -1
  52. package/dist/vue3/components/scroller/scroller.vue.d.ts +6 -8
  53. package/dist/vue3/components/scroller/scroller.vue.d.ts.map +1 -1
  54. package/dist/vue3/components/split_button/split_button.vue.d.ts +4 -4
  55. package/dist/vue3/dialtone-vue.cjs +1 -1
  56. package/dist/vue3/dialtone-vue.js +56 -52
  57. package/dist/vue3/index.d.ts +1 -0
  58. package/dist/vue3/lib/attachment-carousel/attachment-carousel.cjs +1 -1
  59. package/dist/vue3/lib/attachment-carousel/attachment-carousel.js +1 -1
  60. package/dist/vue3/lib/attachment-carousel/index.cjs +1 -1
  61. package/dist/vue3/lib/attachment-carousel/index.js +1 -1
  62. package/dist/vue3/lib/editor/editor.cjs +1 -1
  63. package/dist/vue3/lib/editor/editor.cjs.map +1 -1
  64. package/dist/vue3/lib/editor/editor.js +1 -2
  65. package/dist/vue3/lib/editor/editor.js.map +1 -1
  66. package/dist/vue3/lib/editor/index.cjs +1 -1
  67. package/dist/vue3/lib/editor/index.js +0 -1
  68. package/dist/vue3/lib/message-input/index.cjs +1 -1
  69. package/dist/vue3/lib/message-input/index.js +1 -2
  70. package/dist/vue3/lib/message-input/message-input.cjs +1 -1
  71. package/dist/vue3/lib/message-input/message-input.js +1 -2
  72. package/dist/vue3/lib/resizable/index.cjs +1 -0
  73. package/dist/vue3/lib/resizable/index.js +5 -0
  74. package/dist/vue3/lib/resizable/resizable-handle.cjs +1 -0
  75. package/dist/vue3/lib/resizable/resizable-handle.js +2 -0
  76. package/dist/vue3/lib/resizable/resizable-panel.cjs +2 -0
  77. package/dist/vue3/lib/resizable/resizable-panel.cjs.map +1 -0
  78. package/dist/vue3/lib/resizable/resizable-panel.js +132 -0
  79. package/dist/vue3/lib/resizable/resizable-panel.js.map +1 -0
  80. package/dist/vue3/lib/resizable/resizable.cjs +1 -0
  81. package/dist/vue3/lib/resizable/resizable.js +2 -0
  82. package/dist/vue3/lib/rich-text-editor/index.cjs +1 -1
  83. package/dist/vue3/lib/rich-text-editor/index.js +1 -2
  84. package/dist/vue3/lib/rich-text-editor/markdownRenderer.cjs +1 -1
  85. package/dist/vue3/lib/rich-text-editor/markdownRenderer.js +1 -1
  86. package/dist/vue3/lib/rich-text-editor/rich-text-editor.cjs +1 -1
  87. package/dist/vue3/lib/rich-text-editor/rich-text-editor.js +1 -2
  88. package/dist/vue3/lib/scroller/index.cjs +1 -1
  89. package/dist/vue3/lib/scroller/index.js +1 -1
  90. package/dist/vue3/lib/scroller/scroller.cjs +1 -1
  91. package/dist/vue3/lib/scroller/scroller.js +1 -1
  92. package/dist/vue3/lib/toast/index.cjs +1 -1
  93. package/dist/vue3/lib/toast/index.js +1 -1
  94. package/dist/vue3/lib/toast/toast.cjs +1 -1
  95. package/dist/vue3/lib/toast/toast.js +1 -1
  96. package/dist/vue3/{markdownRenderer-PRpHJ151.cjs → markdownRenderer-DCgGQseq.cjs} +1 -1
  97. package/dist/vue3/{markdownRenderer-PRpHJ151.cjs.map → markdownRenderer-DCgGQseq.cjs.map} +1 -1
  98. package/dist/vue3/{markdownRenderer-D14GhUiu.js → markdownRenderer-D_P94RyM.js} +1 -1
  99. package/dist/vue3/{markdownRenderer-D14GhUiu.js.map → markdownRenderer-D_P94RyM.js.map} +1 -1
  100. package/dist/vue3/{message_input-Bs-fg95i.cjs → message_input-AWgvtwMV.cjs} +2 -2
  101. package/dist/vue3/{message_input-Bs-fg95i.cjs.map → message_input-AWgvtwMV.cjs.map} +1 -1
  102. package/dist/vue3/{message_input-DfcdjT6O.js → message_input-CHlTsBGK.js} +2 -2
  103. package/dist/vue3/{message_input-DfcdjT6O.js.map → message_input-CHlTsBGK.js.map} +1 -1
  104. package/dist/vue3/node_modules/@tiptap/vue-3.cjs.map +1 -1
  105. package/dist/vue3/node_modules/@tiptap/vue-3.js +1 -1
  106. package/dist/vue3/node_modules/@tiptap/vue-3.js.map +1 -1
  107. package/dist/vue3/recipes/conversation_view/editor/editor.vue.d.ts +2 -0
  108. package/dist/vue3/recipes/conversation_view/editor/editor.vue.d.ts.map +1 -1
  109. package/dist/vue3/recipes/conversation_view/message_input/message_input.vue.d.ts +2 -0
  110. package/dist/vue3/recipes/conversation_view/message_input/message_input.vue.d.ts.map +1 -1
  111. package/dist/vue3/resizable-D4-peBOl.js +960 -0
  112. package/dist/vue3/resizable-D4-peBOl.js.map +1 -0
  113. package/dist/vue3/resizable-aOVGO_Os.cjs +2 -0
  114. package/dist/vue3/resizable-aOVGO_Os.cjs.map +1 -0
  115. package/dist/vue3/resizable_handle-BlKBiWnx.js +307 -0
  116. package/dist/vue3/resizable_handle-BlKBiWnx.js.map +1 -0
  117. package/dist/vue3/resizable_handle-RIKS8frB.cjs +2 -0
  118. package/dist/vue3/resizable_handle-RIKS8frB.cjs.map +1 -0
  119. package/dist/vue3/resizable_utils-BComtrMV.js +131 -0
  120. package/dist/vue3/resizable_utils-BComtrMV.js.map +1 -0
  121. package/dist/vue3/resizable_utils-DhuzXRdP.cjs +2 -0
  122. package/dist/vue3/resizable_utils-DhuzXRdP.cjs.map +1 -0
  123. package/dist/vue3/{rich_text_editor-Cu0E6GWr.js → rich_text_editor-Ba67C4Uk.js} +421 -454
  124. package/dist/vue3/rich_text_editor-Ba67C4Uk.js.map +1 -0
  125. package/dist/vue3/rich_text_editor-DMP5eTlf.cjs +10 -0
  126. package/dist/vue3/rich_text_editor-DMP5eTlf.cjs.map +1 -0
  127. package/dist/vue3/{scroller-axSKchCc.js → scroller-BGVDh3sq.js} +1 -1
  128. package/dist/vue3/{scroller-axSKchCc.js.map → scroller-BGVDh3sq.js.map} +1 -1
  129. package/dist/vue3/{scroller-CuYuo1vd.cjs → scroller-CjAsgjl9.cjs} +1 -1
  130. package/dist/vue3/{scroller-CuYuo1vd.cjs.map → scroller-CjAsgjl9.cjs.map} +1 -1
  131. package/dist/vue3/{toast-jpudprAC.js → toast-DvPN-bCi.js} +1 -1
  132. package/dist/vue3/{toast-jpudprAC.js.map → toast-DvPN-bCi.js.map} +1 -1
  133. package/dist/vue3/{toast-BZ8qQHML.cjs → toast-d8_zmgkL.cjs} +1 -1
  134. package/dist/vue3/{toast-BZ8qQHML.cjs.map → toast-d8_zmgkL.cjs.map} +1 -1
  135. package/dist/vue3/useResizableCalculations-BDITle3Q.cjs +2 -0
  136. package/dist/vue3/useResizableCalculations-BDITle3Q.cjs.map +1 -0
  137. package/dist/vue3/useResizableCalculations-DAajatT4.js +80 -0
  138. package/dist/vue3/useResizableCalculations-DAajatT4.js.map +1 -0
  139. package/package.json +3 -3
  140. package/dist/vue3/rich_text_editor-Cu0E6GWr.js.map +0 -1
  141. package/dist/vue3/rich_text_editor-D5_gdzNn.cjs +0 -10
  142. package/dist/vue3/rich_text_editor-D5_gdzNn.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resizable-D4-peBOl.js","names":[],"sources":["../components/resizable/composables/useResizablePanelState.ts","../components/resizable/composables/useResizablePanelControls.ts","../components/resizable/composables/computeLayout.ts","../components/resizable/composables/useResizableStorage.ts","../components/resizable/composables/useResizableGroup.ts","../components/resizable/composables/useResizableDrag.ts","../components/resizable/composables/useResizableAnnouncements.ts","../components/resizable/composables/useResizableOffset.ts","../components/resizable/resizable.vue"],"sourcesContent":["/**\n * Panel State Model\n *\n * Pure functions for panel state creation, constraint calculation, and validation.\n * Single source of truth for all constraint-related logic.\n *\n * Constraint math has been extracted to constraintResolver.ts.\n */\n\nimport { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type { ResizablePanelConfig, ResizablePanelState } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { clampToTier } from './constraintResolver';\n\nimport { calculateConstraintHierarchy } from './constraintResolver';\n\n// Re-export constraint types and functions from constraintResolver\nexport type { ConstraintHierarchy } from './constraintResolver';\nexport { calculateConstraintHierarchy } from './constraintResolver';\n\n/**\n * Apply constraints to a pixel size for a panel.\n *\n * Updates panel's constraint pixel values and returns the constrained size.\n *\n * @param panel - Panel state to update constraints on\n * @param pixelSize - Desired pixel size before constraints\n * @param containerSize - Current container size in pixels\n * @param constraintType - Which constraints to apply: 'user' (default) or 'system'\n * @returns Constrained pixel size respecting bounds\n */\nexport function applyPanelPixelConstraints(\n panel: ResizablePanelState,\n pixelSize: number,\n containerSize: number,\n constraintType: 'user' | 'system' = 'user'\n): number {\n const constraints = calculateConstraintHierarchy(panel, containerSize);\n\n panel.userMinSizePixels = constraints.userMinSizePixels;\n panel.userMaxSizePixels = constraints.userMaxSizePixels;\n panel.systemMinSizePixels = constraints.systemMinSizePixels;\n panel.systemMaxSizePixels = constraints.systemMaxSizePixels;\n panel.collapseSizePixels = constraints.collapseSizePixels;\n\n return clampToTier(pixelSize, constraints, constraintType);\n}\n\n// ============================================================================\n// PANEL STATE CREATION\n// ============================================================================\n\nfunction applyConstraintsToSize(pixelSize: number, minSizePixels?: number, maxSizePixels?: number): number {\n let constrained = pixelSize;\n if (minSizePixels !== undefined) {\n constrained = Math.max(constrained, minSizePixels);\n }\n if (maxSizePixels !== undefined) {\n constrained = Math.min(constrained, maxSizePixels);\n }\n return constrained;\n}\n\nfunction derivePanelBehavioralState(\n panelConfig: ResizablePanelConfig,\n existingPanel?: ResizablePanelState\n): { collapsed: boolean; manualTargetSize: number | undefined } {\n return {\n collapsed: existingPanel?.collapsed ?? Boolean(panelConfig.collapsed),\n manualTargetSize: existingPanel?.manualTargetSize,\n };\n}\n\n/**\n * Create initial panel state from configuration.\n */\nexport function createPanelState(\n panelConfig: ResizablePanelConfig,\n containerSize: number,\n existingPanel?: ResizablePanelState\n): ResizablePanelState {\n const constraints = calculateConstraintHierarchy(panelConfig, containerSize);\n\n const rawPixelSize = parseSizeToPixels(panelConfig.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n const pixelSize = applyConstraintsToSize(rawPixelSize, constraints.userMinSizePixels, constraints.userMaxSizePixels);\n\n const behavioralState = derivePanelBehavioralState(panelConfig, existingPanel);\n const autoCollapsed = existingPanel?.autoCollapsed;\n\n return {\n ...panelConfig,\n pixelSize,\n ...behavioralState,\n userMinSizePixels: constraints.userMinSizePixels,\n userMaxSizePixels: constraints.userMaxSizePixels,\n systemMinSizePixels: constraints.systemMinSizePixels,\n systemMaxSizePixels: constraints.systemMaxSizePixels,\n collapseSizePixels: constraints.collapseSizePixels,\n autoCollapsed,\n };\n}\n\n/**\n * Create panel states for all panels in a configuration array.\n */\nexport function createBasicPanelStates(\n allPanels: ResizablePanelConfig[],\n containerSize: number,\n existingPanels?: ResizablePanelState[]\n): ResizablePanelState[] {\n return allPanels.map(panelConfig => {\n const existingPanel = existingPanels?.find(p => p.id === panelConfig.id);\n return createPanelState(panelConfig, containerSize, existingPanel);\n });\n}\n\n// ============================================================================\n// PANEL STATE VALIDATION\n// ============================================================================\n\n/**\n * Check if a panel pair should be skipped during constraint processing.\n */\nexport function shouldSkipPanelPair(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState): boolean {\n return (\n beforePanel.resizable === false ||\n !!beforePanel.collapsed ||\n afterPanel.resizable === false ||\n !!afterPanel.collapsed\n );\n}\n\n/**\n * Check if a panel pair can be reset to initial sizes.\n */\nexport function canResetPanelPair(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState): boolean {\n return (\n beforePanel.resizable !== false && !beforePanel.collapsed && afterPanel.resizable !== false && !afterPanel.collapsed\n );\n}\n","/**\n * Panel Controls Controller\n *\n * Operations for manipulating panel state: resize, collapse, reset.\n * Receives resizeHandler from Integration layer (single instance pattern).\n */\n\nimport type { Ref } from 'vue';\nimport { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type {\n ResizablePanelState,\n ResizableSizeValue,\n CollapseRule,\n} from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { applyPanelPixelConstraints, canResetPanelPair } from './useResizablePanelState';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * State snapshot captured before a panel is collapsed.\n */\nexport interface PreCollapseState {\n sizes: Map<string, number>;\n manualTargets: Map<string, number | undefined>;\n containerSize: number;\n}\n\nexport type CollapseRequestSource =\n | 'user'\n | 'system'\n | 'prop'\n | 'storage';\n\nexport interface CollapseRequest {\n panelId: string;\n action: 'collapse' | 'expand';\n source: CollapseRequestSource;\n}\n\nexport interface CollapseRequestResult {\n success: boolean;\n reason?: string;\n panelId: string;\n newState: 'collapsed' | 'expanded' | 'unchanged';\n}\n\nexport interface CollapseOptions {\n isAutoCollapse?: boolean;\n}\n\nexport interface ResizablePanelControlsOptions {\n panels: Ref<ResizablePanelState[]>;\n containerSize: Ref<number>;\n containerRef: Ref<HTMLElement | null>;\n onPanelResize: (panelId: string, pixelSize: number) => void;\n onPanelCollapse: (panelId: string, collapsed: boolean) => void;\n updateSavedPanel: (panelId: string, updates: Partial<import('./useResizableStorage').SavedPanelData>) => void;\n}\n\n// ============================================================================\n// MAIN COMPOSABLE\n// ============================================================================\n\nexport function useResizablePanelControls(options: ResizablePanelControlsOptions) {\n const {\n panels,\n containerSize,\n containerRef,\n onPanelResize,\n onPanelCollapse,\n updateSavedPanel,\n } = options;\n\n const preCollapseStates = new Map<string, PreCollapseState>();\n\n // ---- Size Conversion ----\n\n function convertToPixelSize(initialSize: ResizableSizeValue): number {\n return parseSizeToPixels(initialSize, containerSize.value);\n }\n\n // ============================================================================\n // CENTRALIZED COLLAPSE LOGIC\n // ============================================================================\n\n function processCollapseRequest(request: CollapseRequest): CollapseRequestResult {\n const { panelId, action, source } = request;\n const panel = panels.value.find(p => p.id === panelId);\n const isCollapse = action === 'collapse';\n\n const validationResult = validateCollapseRequest(panelId, panel, isCollapse);\n if (validationResult) return validationResult;\n\n if (isCollapse) {\n executeCollapse(panel!, source);\n } else {\n executeExpand(panel!);\n }\n\n onPanelCollapse(panelId, isCollapse);\n if (containerRef.value) {\n containerRef.value.dispatchEvent(new CustomEvent('panels-updated'));\n }\n\n const newState = isCollapse ? 'collapsed' : 'expanded';\n\n return { success: true, panelId, newState };\n }\n\n function validateCollapseRequest(\n panelId: string,\n panel: ResizablePanelState | undefined,\n isCollapse: boolean\n ): CollapseRequestResult | undefined {\n if (!panel) {\n return { success: false, reason: 'Panel not found', panelId, newState: 'unchanged' };\n }\n\n const currentlyCollapsed = panel.collapsed;\n if (isCollapse && currentlyCollapsed) {\n return { success: true, reason: 'Already collapsed', panelId, newState: 'unchanged' };\n }\n if (!isCollapse && !currentlyCollapsed) {\n return { success: true, reason: 'Already expanded', panelId, newState: 'unchanged' };\n }\n if (isCollapse && !panel.collapsible) {\n return { success: false, reason: 'Panel is not collapsible', panelId, newState: 'unchanged' };\n }\n\n return undefined;\n }\n\n function executeCollapse(panel: ResizablePanelState, source: CollapseRequestSource): void {\n const state: PreCollapseState = {\n sizes: new Map(),\n manualTargets: new Map(),\n containerSize: containerSize.value,\n };\n panels.value.forEach(p => {\n state.sizes.set(p.id, p.pixelSize);\n state.manualTargets.set(p.id, p.manualTargetSize);\n });\n preCollapseStates.set(panel.id, state);\n\n updateSavedPanel(panel.id, { collapsed: true, autoCollapsed: source === 'system' });\n\n // Clear manual ratios so remaining panels fill the freed space\n panels.value.forEach(p => {\n if (p.id !== panel.id && !p.collapsed) {\n updateSavedPanel(p.id, { manualTargetRatio: undefined });\n }\n });\n }\n\n function executeExpand(panel: ResizablePanelState): void {\n const wasAutoCollapsed = panel.autoCollapsed ?? false;\n\n const preCollapse = preCollapseStates.get(panel.id);\n\n if (preCollapse) {\n const viewportChangeRatio = Math.abs(containerSize.value - preCollapse.containerSize)\n / preCollapse.containerSize;\n const viewportChanged = viewportChangeRatio > 0.1;\n const shouldRestoreSizes = !viewportChanged || !wasAutoCollapsed;\n\n if (shouldRestoreSizes) {\n const savedPanelSize = preCollapse.sizes.get(panel.id);\n if (savedPanelSize !== undefined) {\n updateSavedPanel(panel.id, { pixelSize: savedPanelSize, collapsed: false, autoCollapsed: undefined });\n } else {\n updateSavedPanel(panel.id, { collapsed: false, autoCollapsed: undefined });\n }\n\n panels.value.forEach(p => {\n if (p.id === panel.id) return;\n const savedSize = preCollapse.sizes.get(p.id);\n const hadManualTargetBefore = preCollapse.manualTargets.get(p.id) !== undefined;\n const hasManualTargetNow = p.manualTargetSize !== undefined;\n\n if (!hadManualTargetBefore && !hasManualTargetNow && savedSize !== undefined) {\n updateSavedPanel(p.id, { pixelSize: savedSize });\n }\n });\n } else {\n updateSavedPanel(panel.id, { collapsed: false, autoCollapsed: undefined });\n }\n\n preCollapseStates.delete(panel.id);\n } else {\n const initialSize = parseSizeToPixels(panel.initialSize ?? DEFAULT_PANEL_SIZE, containerSize.value);\n const constrainedSize = applyPanelPixelConstraints(panel, initialSize, containerSize.value, 'system');\n updateSavedPanel(panel.id, { pixelSize: constrainedSize, collapsed: false, autoCollapsed: undefined });\n }\n }\n\n // ---- Panel Operations ----\n\n function commitPanelSize(panelId: string, pixels: number): void {\n const rounded = Math.round(pixels);\n const cSize = containerSize.value;\n const ratio = cSize > 0 ? rounded / cSize : undefined;\n updateSavedPanel(panelId, { pixelSize: rounded, manualTargetRatio: ratio });\n }\n\n function resizePanel(panelId: string, newPixelSize: number) {\n const panel = panels.value.find(p => p.id === panelId);\n if (!panel || panel.collapsed) return;\n\n const constrainedSize = applyPanelPixelConstraints(panel, newPixelSize, containerSize.value);\n commitPanelSize(panelId, constrainedSize);\n\n onPanelResize(panelId, constrainedSize);\n }\n\n /**\n */\n function collapsePanel(panelId: string, collapsed: boolean, options?: CollapseOptions) {\n const source: CollapseRequestSource = options?.isAutoCollapse ? 'system' : 'prop';\n\n processCollapseRequest({\n panelId,\n action: collapsed ? 'collapse' : 'expand',\n source,\n });\n }\n\n // ---- Panel Reset Operations ----\n\n function resetAdjacentPanels(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState) {\n const combinedSpace = beforePanel.pixelSize + afterPanel.pixelSize;\n const beforeInitial = convertToPixelSize(beforePanel.initialSize || DEFAULT_PANEL_SIZE);\n const afterInitial = convertToPixelSize(afterPanel.initialSize || DEFAULT_PANEL_SIZE);\n const totalInitial = beforeInitial + afterInitial;\n\n const beforeSize = totalInitial > 0\n ? Math.round(combinedSpace * (beforeInitial / totalInitial))\n : Math.round(combinedSpace / 2);\n const afterSize = combinedSpace - beforeSize;\n\n updateSavedPanel(beforePanel.id, {\n pixelSize: beforeSize, manualTargetRatio: undefined,\n });\n updateSavedPanel(afterPanel.id, {\n pixelSize: afterSize, manualTargetRatio: undefined,\n });\n\n onPanelResize(beforePanel.id, beforeSize);\n onPanelResize(afterPanel.id, afterSize);\n }\n\n function resetAllPanelPairs() {\n for (let i = 0; i < panels.value.length - 1; i++) {\n const currentPanel = panels.value[i];\n const nextPanel = panels.value[i + 1];\n\n if (canResetPanelPair(currentPanel, nextPanel)) {\n resetAdjacentPanels(currentPanel, nextPanel);\n }\n }\n }\n\n function resetSpecificPanelPair(beforePanelId?: string, afterPanelId?: string) {\n const beforePanel = beforePanelId ? panels.value.find(p => p.id === beforePanelId) : undefined;\n const afterPanel = afterPanelId ? panels.value.find(p => p.id === afterPanelId) : undefined;\n\n if (beforePanel && afterPanel && canResetPanelPair(beforePanel, afterPanel)) {\n resetAdjacentPanels(beforePanel, afterPanel);\n }\n }\n\n function resetSinglePanel(panelId?: string) {\n if (!panelId) return;\n const panel = panels.value.find(p => p.id === panelId);\n if (!panel || panel.collapsed || panel.resizable === false) return;\n\n const initialSize = convertToPixelSize(panel.initialSize || DEFAULT_PANEL_SIZE);\n const delta = initialSize - panel.pixelSize;\n\n const panelIndex = panels.value.indexOf(panel);\n const adjacentPanel = panels.value.find((p, i) =>\n i !== panelIndex && !p.collapsed && p.resizable !== false\n );\n\n if (!adjacentPanel) return;\n\n const newAdjacentSize = adjacentPanel.pixelSize - delta;\n\n updateSavedPanel(panel.id, {\n pixelSize: initialSize, manualTargetRatio: undefined,\n });\n updateSavedPanel(adjacentPanel.id, { pixelSize: newAdjacentSize });\n\n onPanelResize(panel.id, initialSize);\n onPanelResize(adjacentPanel.id, newAdjacentSize);\n }\n\n function resetPanels(\n beforePanelId?: string,\n afterPanelId?: string,\n behavior: 'both' | 'before' | 'after' | 'all' = 'all'\n ) {\n try {\n if (behavior === 'all') {\n resetAllPanelPairs();\n } else if (behavior === 'before') {\n resetSinglePanel(beforePanelId);\n } else if (behavior === 'after') {\n resetSinglePanel(afterPanelId);\n } else {\n resetSpecificPanelPair(beforePanelId, afterPanelId);\n }\n } catch (error) {\n console.error('[resizable] Error in resetPanels:', error);\n }\n }\n\n // ---- Auto-Collapse/Expand ----\n\n function checkAutoCollapse(): string[] {\n const collapsedPanels: string[] = [];\n const currentContainerSize = containerSize.value;\n\n for (const panel of panels.value) {\n if (panel.collapsed || !panel.collapsible || !panel.collapseSizePixels) {\n continue;\n }\n\n if (currentContainerSize < panel.collapseSizePixels) {\n const result = processCollapseRequest({\n panelId: panel.id,\n action: 'collapse',\n source: 'system',\n });\n\n if (result.newState === 'collapsed') {\n collapsedPanels.push(panel.id);\n }\n }\n }\n\n return collapsedPanels;\n }\n\n function checkAutoExpand(): string[] {\n const expandedPanels: string[] = [];\n const currentContainerSize = containerSize.value;\n\n for (const panel of panels.value) {\n if (!panel.collapsed || !panel.autoCollapsed || !panel.collapseSizePixels) {\n continue;\n }\n\n if (currentContainerSize >= panel.collapseSizePixels) {\n const result = processCollapseRequest({\n panelId: panel.id,\n action: 'expand',\n source: 'system',\n });\n\n if (result.newState === 'expanded') {\n expandedPanels.push(panel.id);\n }\n }\n }\n\n return expandedPanels;\n }\n\n function processAutoCollapseExpand(): { collapsed: string[]; expanded: string[] } {\n const expanded = checkAutoExpand();\n const collapsed = checkAutoCollapse();\n\n return { collapsed, expanded };\n }\n\n return {\n commitPanelSize,\n resizePanel,\n collapsePanel,\n resetPanels,\n processCollapseRequest,\n checkAutoCollapse,\n checkAutoExpand,\n processAutoCollapseExpand,\n };\n}\n\n// ============================================================================\n// COLLAPSE RULE UTILITIES\n// ============================================================================\n\n/**\n * Sorts collapse rules by priority (lower numbers collapse first).\n * Creates a new sorted array - does not mutate the original.\n * Maintains stable sort for rules with equal priority.\n */\nexport function sortCollapseRules(rules: CollapseRule[]): CollapseRule[] {\n if (!rules || rules.length === 0) {\n return [];\n }\n\n const indexed = rules.map((rule, index) => ({ rule, index }));\n\n indexed.sort((a, b) => {\n const priorityDiff = a.rule.priority - b.rule.priority;\n if (priorityDiff !== 0) {\n return priorityDiff;\n }\n return a.index - b.index;\n });\n\n return indexed.map(item => item.rule);\n}\n\n// ============================================================================\n// AUTO-COLLAPSE UTILITIES\n// ============================================================================\n\nfunction getCollapseThreshold(\n panel: ResizablePanelState,\n rule: CollapseRule,\n containerSize: number\n): number | undefined {\n if (rule.minSizeBeforeCollapse !== undefined) {\n return parseSizeToPixels(rule.minSizeBeforeCollapse, containerSize);\n }\n return panel.userMinSizePixels;\n}\n\nfunction shouldPanelCollapse(\n panels: ResizablePanelState[],\n rule: CollapseRule,\n containerSize: number\n): string | undefined {\n const panel = panels.find(p => p.id === rule.panelId);\n\n if (!panel || panel.collapsed) {\n return undefined;\n }\n\n const threshold = getCollapseThreshold(panel, rule, containerSize);\n\n if (threshold === undefined) {\n return undefined;\n }\n\n return panel.pixelSize <= threshold ? panel.id : undefined;\n}\n\n/**\n * Checks which panels should auto-collapse based on their current size and collapse rules.\n * Returns panel IDs in priority order (lowest priority first = first to collapse).\n */\nexport function checkAutoCollapseRules(\n panels: ResizablePanelState[],\n collapseRules: CollapseRule[],\n containerSize: number\n): string[] {\n if (!panels || panels.length === 0 || !collapseRules || collapseRules.length === 0) {\n return [];\n }\n\n const sortedRules = sortCollapseRules(collapseRules);\n\n return sortedRules\n .map(rule => shouldPanelCollapse(panels, rule, containerSize))\n .filter((id): id is string => id !== undefined);\n}\n","/**\n * computeLayout — Pure Layout Engine\n *\n * Takes panel configs + container size and returns positions for every panel\n * and handle. Constraints are applied WITHIN the computation, not after.\n *\n * This is a pure function: no DOM access, no Vue reactivity, no localStorage,\n * no side effects. It takes data in and returns data out.\n *\n * Key design: proportional scaling\n * - Panels with manualTargetRatio scale to their stored ratio each render\n * - Panels without a ratio distribute remaining space proportionally\n * - Fixed panels (resizable: false) keep their exact pixel size\n * - Min/max constraints clamp results; overflow is redistributed in the same pass\n *\n * @see constraintResolver.ts\n */\n\nimport { DEFAULT_PANEL_SIZE, buildHandleId } from '../resizable_constants';\nimport type { ResizablePanelConfig } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { calculateConstraintHierarchy, clampToTier, type ConstraintHierarchy } from './constraintResolver';\n\n// ============================================================================\n// SAVED STATE TYPE (inlined from useResizableStorage — ported in Task #2)\n// ============================================================================\n\n/**\n * Data shape for a single panel's saved state in localStorage.\n * Defined here so computeLayout stays self-contained without depending\n * on the storage composable. useResizableStorage will re-export this\n * type when it is ported.\n */\nexport interface SavedPanelData {\n id: string;\n pixelSize: number;\n collapsed?: boolean;\n /** Whether this panel was auto-collapsed by the system (vs manually by user) */\n autoCollapsed?: boolean;\n /** Proportion of container this panel should occupy (set by drag, used for viewport scaling) */\n manualTargetRatio?: number;\n}\n\n// ============================================================================\n// INPUT / OUTPUT TYPES\n// ============================================================================\n\n/**\n * Input to the layout computation.\n * All values must be resolved before calling (no lazy-loading, no Vue refs).\n */\nexport interface LayoutInput {\n /** Registered panel configurations, in render order */\n panels: ResizablePanelConfig[];\n /** Current container width (row direction) or height (column direction), in pixels */\n containerSize: number;\n /**\n * Saved state from localStorage (optional).\n * When provided, sizes and collapsed state are restored from here.\n * IDs that do not match current panels are ignored.\n * Values that fail validation fall back to initialSize.\n */\n savedState?: SavedPanelData[];\n}\n\n/**\n * Computed position for a single panel.\n * All values are in pixels, relative to the container's top-left corner.\n */\nexport interface PanelPosition {\n id: string;\n /** Distance from the container's left edge to this panel's left edge */\n left: number;\n /** Distance from this panel's right edge to the container's right edge */\n right: number;\n /** Rendered width of the panel (0 when collapsed) */\n width: number;\n /** Whether the panel is currently collapsed */\n collapsed: boolean;\n /** Resolved constraints for this panel at the current container size */\n constraints: ConstraintHierarchy;\n}\n\n/**\n * Computed position for a single drag handle.\n * Handles sit between adjacent visible panels.\n */\nexport interface HandlePosition {\n /** Handle identifier: \"{beforePanelId}:{afterPanelId}\" */\n id: string;\n beforePanelId: string;\n afterPanelId: string;\n /** Pixel offset from the container's left edge to the handle's left edge */\n left: number;\n /**\n * True when the handle should be non-interactive.\n * Set when either adjacent panel is collapsed or resizable: false.\n */\n disabled: boolean;\n}\n\n/**\n * Output of computeLayout.\n * Immutable — create a new layout by calling computeLayout again.\n */\nexport interface LayoutResult {\n panels: Map<string, PanelPosition>;\n handles: HandlePosition[];\n}\n\n// ============================================================================\n// INTERNAL WORKING STATE\n// ============================================================================\n\n/**\n * Internal representation while computing sizes before positions are finalized.\n */\ninterface WorkingPanel {\n config: ResizablePanelConfig;\n constraints: ConstraintHierarchy;\n width: number;\n collapsed: boolean;\n /** True when resizable: false — panel keeps its exact pixel size, no handle rendered */\n isFixed: boolean;\n /**\n * The manual ratio stored from a previous drag (0–1, fraction of container).\n * When present, this panel's target width = manualTargetRatio * containerSize,\n * still subject to constraints.\n */\n manualTargetRatio?: number;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Resolve initial pixel size for a panel from saved state or initialSize config.\n * Returns the raw size before constraint clamping.\n */\nfunction resolveRawSize(\n config: ResizablePanelConfig,\n containerSize: number,\n savedPanel: SavedPanelData | undefined\n): number {\n if (savedPanel !== undefined) {\n const saved = savedPanel.pixelSize;\n // Reject corrupted saved values\n if (!isFinite(saved) || saved < 0 || (containerSize > 0 && saved > containerSize * 2)) {\n return parseSizeToPixels(config.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n }\n return saved;\n }\n\n return parseSizeToPixels(config.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n}\n\n/**\n * Determine whether a panel should be collapsed for a given input.\n * Priority: savedState.collapsed > config.collapsed\n */\nfunction resolveCollapsed(config: ResizablePanelConfig, savedPanel: SavedPanelData | undefined): boolean {\n if (savedPanel !== undefined && savedPanel.collapsed !== undefined) {\n return savedPanel.collapsed;\n }\n return Boolean(config.collapsed);\n}\n\n/**\n * Clamp a width to the constraint window.\n * Returns the clamped value and the amount of overflow/underflow.\n *\n * @param tier - Which constraints to apply:\n * 'user' — user-min/max (for ratio panels, user-dragged sizes)\n * 'system' — system-min/max falling back to user (for proportional panels,\n * viewport-driven redistribution)\n */\nfunction clampToConstraints(\n width: number,\n constraints: ConstraintHierarchy,\n tier: 'user' | 'system' = 'system'\n): { clamped: number; delta: number } {\n const clamped = clampToTier(width, constraints, tier);\n return { clamped, delta: clamped - width };\n}\n\n/**\n * Build the index of saved state for O(1) lookup during panel iteration.\n * Returns undefined if saved state is structurally incompatible with current panels.\n *\n * Incompatible = current panel IDs have entries NOT present in saved state.\n * (Panel IDs that exist in saved state but not current panels are simply ignored.)\n */\nfunction buildSavedIndex(\n savedState: SavedPanelData[] | undefined\n): Map<string, SavedPanelData> | undefined {\n if (!savedState) return undefined;\n return new Map<string, SavedPanelData>(savedState.map(s => [s.id, s]));\n}\n\n// ============================================================================\n// ALGORITHM\n// ============================================================================\n\n/**\n * Step 1: Build working panels with constraints and raw sizes.\n */\nfunction buildWorkingPanels(\n panels: ResizablePanelConfig[],\n containerSize: number,\n savedIndex: Map<string, SavedPanelData> | undefined\n): WorkingPanel[] {\n return panels.map(config => {\n const constraints = calculateConstraintHierarchy(config, containerSize);\n const savedPanel = savedIndex?.get(config.id);\n const collapsed = resolveCollapsed(config, savedPanel);\n const isFixed = config.resizable === false;\n\n const savedRatio = savedPanel?.manualTargetRatio;\n\n let rawWidth: number;\n if (collapsed) {\n rawWidth = 0;\n } else if (savedRatio !== undefined && containerSize > 0) {\n // Scale from ratio — the panel wants (ratio * container) pixels\n rawWidth = savedRatio * containerSize;\n } else {\n rawWidth = resolveRawSize(config, containerSize, savedPanel);\n }\n\n return {\n config,\n constraints,\n width: rawWidth,\n collapsed,\n isFixed,\n manualTargetRatio: savedRatio,\n };\n });\n}\n\n/**\n * Allocate space for Tier 1 (fixed) and Tier 2 (ratio) panels.\n * Mutates panel widths in place. Returns the total reserved space.\n */\nfunction allocateReservedPanels(visiblePanels: WorkingPanel[], containerSize: number): number {\n // Tier 1: Fixed panels (resizable: false)\n let reservedTotal = 0;\n for (const p of visiblePanels) {\n if (p.isFixed) {\n const { clamped } = clampToConstraints(p.width, p.constraints);\n p.width = clamped;\n reservedTotal += clamped;\n }\n }\n\n // Tier 2: Ratio panels (manualTargetRatio) — user constraints only.\n const ratioPanels = visiblePanels.filter(p => !p.isFixed && p.manualTargetRatio !== undefined);\n for (const p of ratioPanels) {\n const targetWidth = (p.manualTargetRatio ?? 0) * containerSize;\n const { clamped } = clampToConstraints(targetWidth, p.constraints, 'user');\n p.width = clamped;\n reservedTotal += clamped;\n }\n\n return reservedTotal;\n}\n\n/**\n * Iteratively clamp proportional panels to their constraint windows and\n * redistribute overflow/underflow to unclamped panels. Applies a final\n * clamp pass to catch floating-point drift.\n */\nfunction constrainAndRedistribute(propPanels: WorkingPanel[]): void {\n const maxPasses = propPanels.length + 1;\n\n for (let pass = 0; pass < maxPasses; pass++) {\n let totalDelta = 0;\n const clampedIds = new Set<string>();\n\n for (const p of propPanels) {\n const { clamped, delta } = clampToConstraints(p.width, p.constraints);\n if (delta !== 0) {\n p.width = clamped;\n clampedIds.add(p.config.id);\n totalDelta += delta;\n }\n }\n\n if (totalDelta === 0) break;\n\n const freePanels = propPanels.filter(p => !clampedIds.has(p.config.id));\n if (freePanels.length === 0) break;\n\n const changePerPanel = -totalDelta / freePanels.length;\n for (const p of freePanels) {\n p.width += changePerPanel;\n }\n }\n\n // Final clamp to catch any floating-point drift\n for (const p of propPanels) {\n const { clamped } = clampToConstraints(p.width, p.constraints);\n p.width = clamped;\n }\n}\n\n/**\n * If total allocated width < containerSize (all proportional panels hit max),\n * expand the last non-fixed visible panel to absorb the gap.\n */\nfunction applyFillGuarantee(visiblePanels: WorkingPanel[], propPanels: WorkingPanel[], containerSize: number): void {\n const allocatedTotal = visiblePanels.reduce((sum, p) => sum + p.width, 0);\n const gap = containerSize - allocatedTotal;\n if (gap > 1) {\n const lastFlexible = [...propPanels].reverse().find(p => !p.isFixed);\n if (lastFlexible) {\n lastFlexible.width += gap;\n }\n }\n}\n\n/**\n * Step 2: Distribute container space among non-collapsed panels.\n *\n * Distribution order (priority, highest first):\n * 1. Fixed panels (`resizable: false`) — keep exact initial pixel size\n * 2. Ratio panels (`manualTargetRatio`) — target (ratio × container), constrained\n * 3. Proportional panels — share remaining space using raw widths as weights\n *\n * After initial allocation, constraints are applied.\n * When a panel is min-clamped (forced larger), the extra space it consumed is\n * taken from unclamped proportional panels. When a panel is max-clamped (forced\n * smaller), the freed space is given back to unclamped proportional panels.\n * This redistribution iterates until stable (all panels within constraints) or\n * until no unclamped panels remain.\n */\nfunction distributeSpace(working: WorkingPanel[], containerSize: number): void {\n // Early exit for zero container\n if (containerSize <= 0) {\n working.forEach(p => {\n if (!p.collapsed) p.width = 0;\n });\n return;\n }\n\n const visiblePanels = working.filter(p => !p.collapsed);\n if (visiblePanels.length === 0) return;\n\n // ── Tier 1 + 2: Fixed and ratio panels ────────────────────────────────────\n const reservedTotal = allocateReservedPanels(visiblePanels, containerSize);\n\n // ── Tier 3: Proportional panels ───────────────────────────────────────────\n const propPanels = visiblePanels.filter(p => !p.isFixed && p.manualTargetRatio === undefined);\n const remainingSpace = Math.max(0, containerSize - reservedTotal);\n\n if (propPanels.length === 0) return;\n\n // Use current raw widths as proportional weights\n const totalPropWeight = propPanels.reduce((sum, p) => sum + Math.max(0, p.width), 0);\n\n // Initial allocation: proportional share of remaining space\n for (const p of propPanels) {\n if (totalPropWeight > 0) {\n p.width = (p.width / totalPropWeight) * remainingSpace;\n } else {\n // All weights are zero — distribute equally\n p.width = remainingSpace / propPanels.length;\n }\n }\n\n // ── Constraint pass with overflow redistribution ──────────────────────────\n constrainAndRedistribute(propPanels);\n\n // ── Fill guarantee ──────────────────────────────────────────────────────\n applyFillGuarantee(visiblePanels, propPanels, containerSize);\n}\n\n/**\n * Distribute +1px to panels with the largest fractional remainders,\n * skipping panels that are at their max constraint or fixed.\n */\nfunction distributeShortfall(remainders: { panel: WorkingPanel; remainder: number }[], shortfall: number): void {\n remainders.sort((a, b) => b.remainder - a.remainder);\n let remaining = shortfall;\n for (const { panel } of remainders) {\n if (remaining <= 0) break;\n const max = panel.constraints.systemMaxSizePixels ?? panel.constraints.userMaxSizePixels ?? Infinity;\n if (panel.width < max && !panel.isFixed) {\n panel.width += 1;\n remaining -= 1;\n }\n }\n}\n\n/**\n * Step 3: Round widths to integers and fix up rounding error.\n *\n * After distributing floating-point widths, some panels get ceil'd and some\n * floor'd. We use a \"largest remainder\" approach so the total always equals\n * the container size exactly (when not fully clamped by constraints).\n */\nfunction roundWidths(working: WorkingPanel[], containerSize: number): void {\n if (containerSize <= 0) return;\n\n const visiblePanels = working.filter(p => !p.collapsed);\n if (visiblePanels.length === 0) return;\n\n // Floor all widths first, collect remainders\n const remainders: { panel: WorkingPanel; remainder: number }[] = [];\n\n for (const p of visiblePanels) {\n const floored = Math.floor(p.width);\n remainders.push({ panel: p, remainder: p.width - floored });\n p.width = floored;\n }\n\n const currentTotal = visiblePanels.reduce((s, p) => s + p.width, 0);\n const shortfall = containerSize - currentTotal;\n\n distributeShortfall(remainders, shortfall);\n}\n\n/**\n * Step 4: Compute absolute left/right positions for each panel.\n */\nfunction computePositions(working: WorkingPanel[], containerSize: number): Map<string, PanelPosition> {\n const result = new Map<string, PanelPosition>();\n let cursor = 0;\n\n for (const p of working) {\n const width = p.collapsed ? 0 : p.width;\n const left = cursor;\n const right = Math.max(0, containerSize - left - width);\n\n result.set(p.config.id, {\n id: p.config.id,\n left,\n right,\n width,\n collapsed: p.collapsed,\n constraints: p.constraints,\n });\n\n cursor += width;\n }\n\n return result;\n}\n\n/**\n * Step 5: Compute handle positions.\n *\n * A handle is only generated for pairs of adjacent panels where BOTH panels\n * are resizable (resizable !== false). Pairs involving a fixed panel are\n * skipped entirely — no ResizableHandle component exists between them, and\n * including them in the array would shift the autoIndex values that handle\n * components use to look up their own position.\n *\n * Its left position equals the right edge of the before-panel.\n * It is disabled when either adjacent panel is collapsed.\n */\nfunction computeHandles(\n panels: ResizablePanelConfig[],\n positions: Map<string, PanelPosition>,\n): HandlePosition[] {\n const handles: HandlePosition[] = [];\n\n for (let i = 0; i < panels.length - 1; i++) {\n const before = panels[i];\n const after = panels[i + 1];\n\n // Skip pairs that involve a fixed (non-resizable) panel.\n // No ResizableHandle component is placed between fixed panels, so\n // generating an entry would misalign autoIndex → handles[] lookups.\n if (before.resizable === false || after.resizable === false) continue;\n\n const beforePos = positions.get(before.id);\n const afterPos = positions.get(after.id);\n\n if (!beforePos || !afterPos) continue;\n\n const disabled = beforePos.collapsed || afterPos.collapsed;\n\n handles.push({\n id: buildHandleId(before.id, after.id),\n beforePanelId: before.id,\n afterPanelId: after.id,\n left: beforePos.left + beforePos.width,\n disabled,\n });\n }\n\n return handles;\n}\n\n// ============================================================================\n// PUBLIC API\n// ============================================================================\n\n/**\n * Compute the complete layout for a group of resizable panels.\n *\n * This is a pure function — it has no side effects and does not read from\n * or write to the DOM, Vue reactivity, or localStorage.\n *\n * @param input - Panel configs, container size, and optional saved state\n * @returns Immutable layout result with panel positions and handle positions\n *\n * @example\n * const layout = computeLayout({\n * panels: registeredPanels,\n * containerSize: containerWidth,\n * savedState: loadFromStorage(),\n * });\n * const feedPos = layout.panels.get('feed-panel');\n * // feedPos.left, feedPos.width, feedPos.right, feedPos.collapsed\n */\nexport function computeLayout(input: LayoutInput): LayoutResult {\n const { panels, containerSize, savedState } = input;\n\n // Degenerate cases\n if (panels.length === 0) {\n return { panels: new Map(), handles: [] };\n }\n\n // Build saved-state lookup (returns undefined if incompatible with current panels)\n const savedIndex = buildSavedIndex(savedState);\n\n const working = buildWorkingPanels(panels, containerSize, savedIndex);\n distributeSpace(working, containerSize);\n roundWidths(working, containerSize);\n const positions = computePositions(working, containerSize);\n const handles = computeHandles(panels, positions);\n\n return { panels: positions, handles };\n}\n","import { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type { ResizablePanelConfig, ResizablePanelState } from '../resizable_constants';\nimport type { ResizableStorageAdapter, ResizableStoragePanelData } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\n\n// Re-export for backward compatibility\nexport type SavedPanelData = ResizableStoragePanelData;\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\nfunction validateRequiredProperties(data: Record<string, unknown>): boolean {\n return typeof data.id === 'string' && typeof data.pixelSize === 'number' && data.pixelSize >= 0;\n}\n\nfunction validateOptionalProperties(data: Record<string, unknown>): boolean {\n return (\n (data.collapsed === undefined || typeof data.collapsed === 'boolean') &&\n (data.autoCollapsed === undefined || typeof data.autoCollapsed === 'boolean')\n );\n}\n\nfunction isSavedPanelData(obj: unknown): obj is ResizableStoragePanelData {\n if (typeof obj !== 'object' || obj === null) return false;\n const data = obj as Record<string, unknown>;\n return validateRequiredProperties(data) && validateOptionalProperties(data);\n}\n\nfunction isSavedPanelDataArray(obj: unknown): obj is ResizableStoragePanelData[] {\n return Array.isArray(obj) && obj.every(item => isSavedPanelData(item));\n}\n\n/**\n * Validates a stored panel size against container bounds and returns a safe value.\n *\n * Checks for non-finite values, negative values, and oversized values (> 2x container).\n */\nexport function validateStoredPanelSize(\n storedSize: number,\n containerSize: number,\n panelConfig: ResizablePanelConfig\n): number {\n if (!isFinite(storedSize) || storedSize < 0) {\n return parseSizeToPixels(panelConfig.initialSize || DEFAULT_PANEL_SIZE, containerSize);\n }\n\n if (containerSize > 0 && storedSize > containerSize * 2) {\n console.warn(\n `[resizable] Stored size ${storedSize}px for panel '${panelConfig.id}' exceeds 2x container (${containerSize}px). Resetting.`\n );\n return parseSizeToPixels(panelConfig.initialSize || DEFAULT_PANEL_SIZE, containerSize);\n }\n\n return storedSize;\n}\n\n// ============================================================================\n// LOCALSTORAGE ADAPTER\n// ============================================================================\n\n/**\n * Create a localStorage-backed storage adapter.\n *\n * @param key - The localStorage key to use\n * @returns A ResizableStorageAdapter backed by localStorage\n *\n * @example\n * ```vue\n * <dt-resizable :storage=\"localStorageAdapter('my-layout')\">\n * ```\n */\nexport function localStorageAdapter(key: string): ResizableStorageAdapter {\n return {\n save(data: ResizableStoragePanelData[]): void {\n try {\n localStorage.setItem(key, JSON.stringify(data));\n } catch (error) {\n console.error('[resizable] Failed to save to localStorage:', error);\n }\n },\n\n load(): ResizableStoragePanelData[] | null {\n try {\n const saved = localStorage.getItem(key);\n if (!saved) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(saved);\n } catch {\n localStorage.removeItem(key);\n return null;\n }\n\n if (!isSavedPanelDataArray(parsed)) {\n localStorage.removeItem(key);\n return null;\n }\n\n return parsed;\n } catch (error) {\n console.warn('[resizable] Failed to load from localStorage:', error);\n try { localStorage.removeItem(key); } catch { /* ignore */ }\n return null;\n }\n },\n\n clear(): void {\n try {\n localStorage.removeItem(key);\n } catch { /* ignore */ }\n },\n };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\n/**\n * Composable for managing panel persistence.\n *\n * Accepts either a storageKey (string → auto-creates localStorage adapter)\n * or a custom ResizableStorageAdapter. The adapter takes precedence.\n *\n * @param storageKeyOrAdapter - localStorage key string, or null\n * @param customAdapter - Optional custom adapter (overrides storageKey)\n */\nexport function useResizableStorage(\n storageKeyOrAdapter: string | null,\n customAdapter?: ResizableStorageAdapter\n) {\n // Resolve the adapter: custom > storageKey > null\n const adapter: ResizableStorageAdapter | null = customAdapter\n ?? (storageKeyOrAdapter ? localStorageAdapter(storageKeyOrAdapter) : null);\n\n function saveToStorage(panels: ResizableStoragePanelData[] | ResizablePanelState[]): void {\n if (!adapter) return;\n\n const data: ResizableStoragePanelData[] = panels.map(panel => ({\n id: panel.id,\n pixelSize: panel.pixelSize,\n collapsed: panel.collapsed,\n autoCollapsed: panel.autoCollapsed,\n }));\n\n adapter.save(data);\n }\n\n function loadFromStorage(): ResizableStoragePanelData[] | null {\n if (!adapter) return null;\n\n const data = adapter.load();\n if (!data) return null;\n\n // Re-validate even if adapter returned data (defense in depth)\n if (!isSavedPanelDataArray(data)) {\n adapter.clear();\n return null;\n }\n\n return data;\n }\n\n function restorePanelFromStorage(panel: ResizablePanelState, savedPanel: ResizableStoragePanelData): void {\n if (panel.restoredFromStorage) return;\n\n if (savedPanel.pixelSize !== undefined) {\n panel.pixelSize = savedPanel.pixelSize;\n }\n if (savedPanel.collapsed !== undefined) {\n panel.collapsed = savedPanel.collapsed;\n }\n if (savedPanel.autoCollapsed !== undefined) {\n panel.autoCollapsed = savedPanel.autoCollapsed;\n }\n\n panel.restoredFromStorage = true;\n }\n\n function loadFromStorageWithValidation(panels: ResizablePanelState[]): boolean {\n const savedState = loadFromStorage();\n if (!savedState) return false;\n\n const currentPanelIds = new Set(panels.map(p => p.id));\n const savedPanelIds = new Set(savedState.map(p => p.id));\n\n // Clear if current panels don't all exist in saved (panel config changed)\n const hasIncompatiblePanels = Array.from(currentPanelIds).some(id => !savedPanelIds.has(id));\n if (hasIncompatiblePanels) {\n if (adapter) adapter.clear();\n return false;\n }\n\n savedState.forEach(savedPanel => {\n const panel = panels.find(p => p.id === savedPanel.id);\n if (panel) restorePanelFromStorage(panel, savedPanel);\n });\n\n return true;\n }\n\n function clearStorage(): void {\n if (adapter) adapter.clear();\n }\n\n return {\n saveToStorage,\n loadFromStorage,\n loadFromStorageWithValidation,\n restorePanelFromStorage,\n clearStorage,\n };\n}\n","/**\n * useResizableGroup — Reactive Layout Controller\n *\n * Replaces the timer-based initialization flow with a Vue `computed` that\n * re-runs synchronously whenever panels or the container size change.\n *\n * Responsibilities:\n * - Maintain the `registeredPanels` ref (panels call registerPanel/unregisterPanel)\n * - Track `containerSize` via a ResizeObserver (set up here, not in the component)\n * - Load saved state ONCE synchronously at creation time\n * - Expose `layout` computed that calls `computeLayout()`\n * - Expose `syncedPanels` computed that converts `LayoutResult` to `ResizablePanelState[]`\n *\n * @see computeLayout.ts — the pure layout engine\n */\n\nimport { ref, computed, watch, nextTick, type ComputedRef, type Ref } from 'vue';\nimport type { ResizablePanelConfig, ResizablePanelState, ResizableDirection } from '../resizable_constants';\nimport type { LayoutResult } from './computeLayout';\nimport type { SavedPanelData } from './useResizableStorage';\nimport { computeLayout } from './computeLayout';\nimport { useResizableStorage } from './useResizableStorage';\nimport { calculateConstraintHierarchy } from './constraintResolver';\nimport { validateContainerSize } from '../resizable_utils';\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport interface UseResizableGroupOptions {\n storageKey: string | null;\n direction: ComputedRef<ResizableDirection>;\n containerRef: Ref<HTMLElement | null>;\n /** Custom storage adapter. Overrides storageKey when provided. */\n storageAdapter?: import('../resizable_constants').ResizableStorageAdapter;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/** Clamp a container dimension to a valid range. Delegates to the shared utility. */\nconst clampContainerSize = validateContainerSize;\n\n/**\n * Build a `ResizablePanelState` from a panel config + the layout result.\n * Reads `manualTargetRatio` and `autoCollapsed` from savedState.\n */\nfunction buildPanelState(\n config: ResizablePanelConfig,\n containerSize: number,\n layoutResult: LayoutResult,\n saved: SavedPanelData | undefined\n): ResizablePanelState {\n const position = layoutResult.panels.get(config.id);\n const constraints = position?.constraints ?? calculateConstraintHierarchy(config, containerSize);\n\n const pixelSize = position?.width ?? 0;\n const collapsed = position?.collapsed ?? Boolean(config.collapsed);\n\n return {\n ...config,\n pixelSize,\n collapsed,\n userMinSizePixels: constraints.userMinSizePixels,\n userMaxSizePixels: constraints.userMaxSizePixels,\n systemMinSizePixels: constraints.systemMinSizePixels,\n systemMaxSizePixels: constraints.systemMaxSizePixels,\n collapseSizePixels: constraints.collapseSizePixels,\n manualTargetRatio: saved?.manualTargetRatio,\n autoCollapsed: saved?.autoCollapsed,\n };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\nexport function useResizableGroup(options: UseResizableGroupOptions) {\n const { storageKey, direction, containerRef } = options;\n\n // ── Panel registry ──────────────────────────────────────────────────────────\n const registeredPanels = ref<ResizablePanelConfig[]>([]);\n\n // ── Container size ──────────────────────────────────────────────────────────\n const containerSize = ref(0);\n\n // ── Storage ─────────────────────────────────────────────────────────────────\n const storage = useResizableStorage(storageKey, options.storageAdapter);\n const savedState = ref<SavedPanelData[] | null>(storage.loadFromStorage());\n\n // ── isInitializing ─────────────────────────────────────────────────────────\n const isInitializing = ref(true);\n\n // ── Layout computed ─────────────────────────────────────────────────────────\n const layout = computed((): LayoutResult => {\n const panels = registeredPanels.value;\n const size = containerSize.value;\n\n if (panels.length === 0 || size <= 0) {\n return { panels: new Map(), handles: [] };\n }\n\n return computeLayout({\n panels,\n containerSize: size,\n savedState: savedState.value ?? undefined,\n });\n });\n\n // ── syncedPanels computed ───────────────────────────────────────────────────\n const syncedPanels = computed((): ResizablePanelState[] => {\n const result = layout.value;\n const size = containerSize.value;\n const savedMap = new Map(savedState.value?.map(s => [s.id, s]) ?? []);\n\n return registeredPanels.value.map(config => {\n const saved = savedMap.get(config.id);\n return buildPanelState(config, size, result, saved);\n });\n });\n\n // Flip isInitializing to false after first successful layout\n watch(\n layout,\n result => {\n if (result.panels.size > 0 && isInitializing.value) {\n isInitializing.value = false;\n }\n },\n { immediate: true }\n );\n\n // ── Panel index (O(1) lookup by id) ────────────────────────────────────────\n const panelMap = computed((): Map<string, ResizablePanelState> => {\n const map = new Map<string, ResizablePanelState>();\n for (const p of syncedPanels.value) map.set(p.id, p);\n return map;\n });\n\n // ── Panel registration ──────────────────────────────────────────────────────\n\n let sortScheduled = false;\n\n function registerPanel(config: ResizablePanelConfig): void {\n if (config.id.includes(':')) {\n console.warn(\n `[resizable] Panel id \"${config.id}\" contains ':' which is reserved as the handle separator. Use kebab-case.`\n );\n }\n\n const index = registeredPanels.value.findIndex(p => p.id === config.id);\n if (index !== -1) {\n registeredPanels.value = registeredPanels.value.map((p, i) => (i === index ? config : p));\n } else {\n registeredPanels.value = [...registeredPanels.value, config];\n\n if (!sortScheduled) {\n sortScheduled = true;\n nextTick(() => {\n registeredPanels.value = sortByDOMOrder(registeredPanels.value);\n sortScheduled = false;\n });\n }\n }\n }\n\n /**\n * Sort panel configs to match DOM order inside the container element.\n */\n function sortByDOMOrder(panels: ResizablePanelConfig[]): ResizablePanelConfig[] {\n const container = containerRef.value;\n if (!container) return panels;\n\n const panelElements = Array.from(container.querySelectorAll<HTMLElement>('.d-resizable-panel[data-panel-id]'));\n if (panelElements.length === 0) return panels;\n\n const domOrder = new Map<string, number>();\n panelElements.forEach((el, i) => {\n const id = el.getAttribute('data-panel-id');\n if (id) domOrder.set(id, i);\n });\n\n return [...panels].sort((a, b) => {\n const aPos = domOrder.get(a.id) ?? Infinity;\n const bPos = domOrder.get(b.id) ?? Infinity;\n return aPos - bPos;\n });\n }\n\n function unregisterPanel(id: string): void {\n registeredPanels.value = registeredPanels.value.filter(p => p.id !== id);\n }\n\n // ── Storage operations ──────────────────────────────────────────────────────\n\n function saveCurrentLayout(panels: ResizablePanelState[]): void {\n storage.saveToStorage(panels);\n savedState.value = panels.map(p => ({\n id: p.id,\n pixelSize: p.pixelSize,\n collapsed: p.collapsed,\n autoCollapsed: p.autoCollapsed,\n manualTargetRatio: p.manualTargetRatio,\n }));\n }\n\n function updateSavedPanel(panelId: string, updates: Partial<SavedPanelData>): void {\n if (!savedState.value) savedState.value = [];\n const idx = savedState.value.findIndex(s => s.id === panelId);\n if (idx >= 0) {\n savedState.value[idx] = { ...savedState.value[idx], ...updates };\n } else {\n // Use current computed size as default, not 0\n const currentPanel = syncedPanels.value.find(p => p.id === panelId);\n const currentSize = currentPanel?.pixelSize ?? 0;\n savedState.value.push({ id: panelId, pixelSize: currentSize, ...updates });\n }\n savedState.value = [...savedState.value]; // trigger reactivity\n\n // Persist to external storage\n storage.saveToStorage(savedState.value);\n }\n\n function reloadFromStorage(): void {\n savedState.value = storage.loadFromStorage();\n }\n\n function clearSavedState(): void {\n storage.clearStorage();\n savedState.value = null;\n }\n\n // ── ResizeObserver ─────────────────────────────────────────────────────────\n\n const resizeObserver = new ResizeObserver(entries => {\n for (const entry of entries) {\n const dim = direction.value === 'row' ? entry.contentRect.width : entry.contentRect.height;\n containerSize.value = clampContainerSize(Math.round(dim));\n }\n });\n\n function disconnectObserver(): void {\n resizeObserver.disconnect();\n }\n\n watch(\n containerRef,\n (el, prev) => {\n if (prev) resizeObserver.unobserve(prev);\n if (el) {\n const initial = direction.value === 'row' ? el.clientWidth : el.clientHeight;\n containerSize.value = clampContainerSize(initial);\n resizeObserver.observe(el);\n }\n },\n { immediate: true }\n );\n\n // ── Expose ─────────────────────────────────────────────────────────────────\n\n return {\n layout,\n syncedPanels,\n panelMap,\n containerSize,\n isInitializing,\n\n registerPanel,\n unregisterPanel,\n\n saveCurrentLayout,\n updateSavedPanel,\n reloadFromStorage,\n clearSavedState,\n\n disconnectObserver,\n };\n}\n","/**\n * useResizableDrag — Per-group drag state composable\n *\n * Each ResizableGroup instance gets its own drag composable, so nested groups can\n * drag independently without conflict.\n *\n * Key design: shadow state during drag.\n * - proposedBeforeSize / proposedAfterSize track the \"what-if\" layout during the drag.\n * - These are applied directly to DOM elements as inline styles (performance).\n * - The reactive layout state is NOT mutated during drag.\n * - On commit (mouseup / touchend): onDragEnd callback receives the final sizes.\n * - On cancel (Escape / unmount): inline styles are removed, DOM returns to layout state.\n */\n\nimport { reactive, onUnmounted, type ComputedRef, type Ref } from 'vue';\nimport type { ResizableDirection, ResizablePanelState } from '../resizable_constants';\nimport type { ResizeHandler } from './useResizableCalculations';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport type DragState = DragStateIdle | DragStateActive;\n\nexport interface DragStateIdle {\n isActive: false;\n handleId: null;\n beforePanelId: null;\n afterPanelId: null;\n proposedBeforeSize: 0;\n proposedAfterSize: 0;\n}\n\nexport interface DragStateActive {\n isActive: true;\n handleId: string;\n beforePanelId: string;\n afterPanelId: string;\n /** Proposed before-panel size during drag (shadow — not committed to layout yet) */\n proposedBeforeSize: number;\n /** Proposed after-panel size during drag (shadow — not committed to layout yet) */\n proposedAfterSize: number;\n}\n\n/** Initial idle state for reactive() initialization. */\nconst IDLE_STATE: DragStateIdle = {\n isActive: false,\n handleId: null,\n beforePanelId: null,\n afterPanelId: null,\n proposedBeforeSize: 0,\n proposedAfterSize: 0,\n};\n\nexport interface UseResizableDragOptions {\n direction: ComputedRef<ResizableDirection>;\n containerRef: Ref<HTMLElement | null>;\n panels: ComputedRef<ResizablePanelState[]> | Ref<ResizablePanelState[]>;\n containerSize: ComputedRef<number> | Ref<number>;\n resizeHandler: ResizeHandler;\n onDragEnd: (\n beforePanelId: string,\n afterPanelId: string,\n beforeSize: number,\n afterSize: number,\n sizesChanged: boolean\n ) => void;\n onDragStart?: (handleId: string) => void;\n}\n\n// ============================================================================\n// DOM HELPERS\n// ============================================================================\n\nfunction findPanelElement(container: HTMLElement, panelId: string): HTMLElement | null {\n return container.querySelector<HTMLElement>(`[data-panel-id=\"${panelId}\"]`);\n}\n\nfunction findHandleElement(container: HTMLElement, handleId: string): HTMLElement | null {\n return container.querySelector<HTMLElement>(`[data-handle-id=\"${handleId}\"]`);\n}\n\nfunction applyPanelDragStyle(element: HTMLElement, start: number, end: number): void {\n element.style.insetInlineStart = `${start}px`;\n element.style.insetInlineEnd = `${end}px`;\n element.style.inlineSize = '';\n}\n\nfunction clearDragStyle(element: HTMLElement): void {\n element.style.insetInlineStart = '';\n element.style.insetInlineEnd = '';\n element.style.inlineSize = '';\n}\n\nfunction applyHandleDragStyle(element: HTMLElement, position: number): void {\n element.style.insetInlineStart = `${Math.max(0, position)}px`;\n}\n\nfunction clearHandleDragStyle(element: HTMLElement): void {\n element.style.insetInlineStart = '';\n}\n\n// ============================================================================\n// PANEL LOOKUP\n// ============================================================================\n\n/**\n * Find the before/after panel pair for a given handle ID.\n * Handle IDs are formatted as \"{beforePanelId}:{afterPanelId}\".\n */\nexport function findPanelsForHandle(\n handleId: string,\n panels: ResizablePanelState[]\n): { beforePanel: ResizablePanelState | null; afterPanel: ResizablePanelState | null } {\n const sepIndex = handleId.indexOf(':');\n if (sepIndex === -1) return { beforePanel: null, afterPanel: null };\n\n const beforeId = handleId.slice(0, sepIndex);\n const afterId = handleId.slice(sepIndex + 1);\n\n const beforePanel = panels.find(p => p.id === beforeId) ?? null;\n const afterPanel = panels.find(p => p.id === afterId) ?? null;\n return { beforePanel, afterPanel };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\n/**\n * Must be called from component setup context (uses `onUnmounted` lifecycle hook).\n */\nexport function useResizableDrag(options: UseResizableDragOptions) {\n const { direction, containerRef, panels, containerSize, resizeHandler, onDragEnd, onDragStart } = options;\n\n const dragState = reactive<DragState>({ ...IDLE_STATE });\n\n let beforePanelEl: HTMLElement | null = null;\n let afterPanelEl: HTMLElement | null = null;\n let handleEl: HTMLElement | null = null;\n\n let cachedBeforePanel: ResizablePanelState | null = null;\n let cachedAfterPanel: ResizablePanelState | null = null;\n\n let originalBeforeSize = 0;\n let originalAfterSize = 0;\n let beforePanelLeft = 0;\n let cachedContainerRect: DOMRect | null = null;\n\n let boundPointerMove: ((e: PointerEvent) => void) | null = null;\n let boundPointerUp: ((e: PointerEvent) => void) | null = null;\n\n function attachDocumentListeners(): void {\n boundPointerMove = (e: PointerEvent) => onDragMove(e);\n boundPointerUp = () => commitDrag();\n\n document.addEventListener('pointermove', boundPointerMove);\n document.addEventListener('pointerup', boundPointerUp);\n document.addEventListener('pointercancel', boundPointerUp);\n document.addEventListener('keydown', handleKeydown);\n }\n\n function removeDocumentListeners(): void {\n if (boundPointerMove) {\n document.removeEventListener('pointermove', boundPointerMove);\n boundPointerMove = null;\n }\n if (boundPointerUp) {\n document.removeEventListener('pointerup', boundPointerUp);\n document.removeEventListener('pointercancel', boundPointerUp);\n boundPointerUp = null;\n }\n document.removeEventListener('keydown', handleKeydown);\n }\n\n function cleanup(): void {\n removeDocumentListeners();\n\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n\n Object.assign(dragState, IDLE_STATE);\n\n beforePanelEl = null;\n afterPanelEl = null;\n handleEl = null;\n cachedBeforePanel = null;\n cachedAfterPanel = null;\n originalBeforeSize = 0;\n originalAfterSize = 0;\n beforePanelLeft = 0;\n cachedContainerRect = null;\n }\n\n function locateDragElements(\n container: HTMLElement,\n handleId: string,\n panelList: ResizablePanelState[]\n ): {\n beforePanel: ResizablePanelState;\n afterPanel: ResizablePanelState;\n beforeEl: HTMLElement;\n afterEl: HTMLElement;\n handleElement: HTMLElement | null;\n } | null {\n const { beforePanel, afterPanel } = findPanelsForHandle(handleId, panelList);\n if (!beforePanel || !afterPanel) {\n console.warn(`[resizable] No panel pair found for handle \"${handleId}\"`);\n return null;\n }\n\n const beforeEl = findPanelElement(container, beforePanel.id);\n const afterEl = findPanelElement(container, afterPanel.id);\n const handleElement = findHandleElement(container, handleId);\n\n if (!beforeEl || !afterEl) {\n console.warn(`[resizable] Panel element(s) not found for handle \"${handleId}\"`);\n return null;\n }\n\n return { beforePanel, afterPanel, beforeEl, afterEl, handleElement };\n }\n\n function startDrag(handleId: string): void {\n const container = containerRef.value;\n if (!container) return;\n\n const elements = locateDragElements(container, handleId, panels.value);\n if (!elements) return;\n\n beforePanelEl = elements.beforeEl;\n afterPanelEl = elements.afterEl;\n handleEl = elements.handleElement;\n\n cachedBeforePanel = elements.beforePanel;\n cachedAfterPanel = elements.afterPanel;\n\n originalBeforeSize = elements.beforePanel.pixelSize;\n originalAfterSize = elements.afterPanel.pixelSize;\n\n beforePanelLeft = parseFloat(beforePanelEl.style.insetInlineStart || '0');\n cachedContainerRect = container.getBoundingClientRect();\n\n Object.assign(dragState, {\n isActive: true,\n handleId,\n beforePanelId: elements.beforePanel.id,\n afterPanelId: elements.afterPanel.id,\n proposedBeforeSize: originalBeforeSize,\n proposedAfterSize: originalAfterSize,\n } satisfies DragStateActive);\n\n document.body.style.userSelect = 'none';\n document.body.style.cursor = direction.value === 'row' ? 'ew-resize' : 'ns-resize';\n\n attachDocumentListeners();\n onDragStart?.(handleId);\n }\n\n function computeDragPosition(\n event: PointerEvent,\n dir: ResizableDirection\n ): number {\n const rect = cachedContainerRect!;\n return dir === 'row' ? event.clientX - rect.left : event.clientY - rect.top;\n }\n\n function isDragMoveReady(): boolean {\n return (\n dragState.isActive &&\n !!containerRef.value &&\n !!beforePanelEl &&\n !!afterPanelEl &&\n !!dragState.handleId &&\n !!cachedBeforePanel &&\n !!cachedAfterPanel\n );\n }\n\n function onDragMove(event: PointerEvent): void {\n if (!isDragMoveReady()) return;\n\n const rawCursorPosition = computeDragPosition(event, direction.value);\n\n const result = resizeHandler.processResizeMove(\n rawCursorPosition,\n cachedBeforePanel!,\n cachedAfterPanel!,\n containerSize.value,\n dragState.handleId!,\n panels.value,\n beforePanelLeft\n );\n\n if (!result.isValidResize) return;\n\n if (dragState.proposedBeforeSize !== result.beforePanelSize) {\n dragState.proposedBeforeSize = result.beforePanelSize;\n }\n if (dragState.proposedAfterSize !== result.afterPanelSize) {\n dragState.proposedAfterSize = result.afterPanelSize;\n }\n\n const containerSizeValue = containerSize.value;\n const constrainedCursor = result.constrainedCursorPosition;\n const beforeRight = containerSizeValue - constrainedCursor;\n const handlePos = constrainedCursor - 2;\n\n const afterRight = containerSizeValue - constrainedCursor - result.afterPanelSize;\n\n applyPanelDragStyle(beforePanelEl!, beforePanelLeft, beforeRight);\n applyPanelDragStyle(afterPanelEl!, constrainedCursor, Math.max(0, afterRight));\n\n if (handleEl) {\n applyHandleDragStyle(handleEl, handlePos);\n }\n }\n\n function commitDrag(): void {\n if (!dragState.isActive) return;\n\n const beforePanelId = dragState.beforePanelId;\n const afterPanelId = dragState.afterPanelId;\n const beforeSize = dragState.proposedBeforeSize;\n const afterSize = dragState.proposedAfterSize;\n\n const capturedOriginalBeforeSize = originalBeforeSize;\n const capturedOriginalAfterSize = originalAfterSize;\n\n if (beforePanelEl) clearDragStyle(beforePanelEl);\n if (afterPanelEl) clearDragStyle(afterPanelEl);\n if (handleEl) clearHandleDragStyle(handleEl);\n\n cleanup();\n\n const sizesChanged = beforeSize !== capturedOriginalBeforeSize || afterSize !== capturedOriginalAfterSize;\n\n if (beforePanelId && afterPanelId) {\n onDragEnd(beforePanelId, afterPanelId, beforeSize, afterSize, sizesChanged);\n }\n }\n\n function cancelDrag(): void {\n if (!dragState.isActive) return;\n\n if (beforePanelEl && afterPanelEl) {\n clearDragStyle(beforePanelEl);\n clearDragStyle(afterPanelEl);\n }\n if (handleEl) {\n clearHandleDragStyle(handleEl);\n }\n\n cleanup();\n }\n\n function handleKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && dragState.isActive) {\n event.preventDefault();\n cancelDrag();\n }\n }\n\n onUnmounted(() => {\n cancelDrag();\n });\n\n return {\n dragState,\n startDrag,\n onDragMove,\n commitDrag,\n cancelDrag,\n cleanup,\n };\n}\n","import { onMounted, onUnmounted } from 'vue';\n\n// ─── Announcements (aria-live singleton with ref counting) ───────────────\n\nlet announcementElement: HTMLElement | null = null;\nlet announcementTimeout: ReturnType<typeof setTimeout> | undefined;\nlet announcementRefCount = 0;\n\nfunction getAnnouncementElement(): HTMLElement {\n if (!announcementElement) {\n announcementElement = document.getElementById('d-resizable-announcements');\n\n if (!announcementElement) {\n announcementElement = document.createElement('div');\n announcementElement.id = 'd-resizable-announcements';\n announcementElement.setAttribute('aria-live', 'polite');\n announcementElement.setAttribute('aria-atomic', 'true');\n announcementElement.style.position = 'absolute';\n announcementElement.style.left = '-10000px';\n announcementElement.style.width = '1px';\n announcementElement.style.height = '1px';\n announcementElement.style.overflow = 'hidden';\n document.body.appendChild(announcementElement);\n }\n }\n return announcementElement;\n}\n\nfunction announce(message: string): void {\n if (!message.trim()) return;\n\n if (announcementTimeout) {\n clearTimeout(announcementTimeout);\n }\n\n const element = getAnnouncementElement();\n element.textContent = '';\n\n announcementTimeout = setTimeout(() => {\n element.textContent = message;\n setTimeout(() => { element.textContent = ''; }, 1000);\n }, 100);\n}\n\n// ─── Composable ───────────────────────────────────────────────────────────\n\n/**\n * Manages a shared aria-live announcements region for all DtResizable\n * instances. Uses ref counting to create/destroy the singleton DOM element.\n */\nexport function useResizableAnnouncements() {\n onMounted(() => {\n announcementRefCount++;\n getAnnouncementElement();\n });\n\n onUnmounted(() => {\n if (announcementTimeout) {\n clearTimeout(announcementTimeout);\n }\n\n announcementRefCount--;\n if (announcementRefCount <= 0 && announcementElement) {\n announcementElement.remove();\n announcementElement = null;\n announcementRefCount = 0;\n }\n });\n\n return { announce };\n}\n","/**\n * Offset positioning composable for resize handles.\n *\n * Calculates dynamic offsets from DOM elements (e.g. a fixed header/toolbar)\n * so handles and panel content can avoid overlapping external UI.\n */\n\nimport {\n ref,\n computed,\n onMounted,\n type Ref,\n type ComputedRef,\n} from 'vue';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface ResizableOffsetOptions {\n /** CSS selector for the element to measure offset from (auto-measures block-size) */\n offsetElement?: string | null;\n /** Explicit pixel offset. Overrides offsetElement measurement when both provided. */\n offsetAmount?: number | null;\n /** Which edge(s) the offset applies to (default: 'start') */\n offsetDirection?: 'start' | 'end' | 'both';\n /** Layout direction — affects which dimension is measured */\n direction?: ComputedRef<'row' | 'column'> | Ref<'row' | 'column'>;\n}\n\nexport interface ResizableOffsetResult {\n calculatedOffset: Ref<number>;\n updateOffset: () => void;\n handleStyles: ComputedRef<Record<string, string>>;\n contentStyles: ComputedRef<Record<string, string>>;\n}\n\n// ─── Composable ───────────────────────────────────────────────────────────\n\nexport function useResizableOffset(\n options: ResizableOffsetOptions = {},\n): ResizableOffsetResult {\n const {\n offsetElement = null,\n offsetAmount = null,\n offsetDirection = 'start',\n direction = ref('row'),\n } = options;\n\n const calculatedOffset = ref(0);\n\n function updateOffset(): void {\n // Explicit amount wins over element measurement\n if (offsetAmount != null && offsetAmount > 0) {\n calculatedOffset.value = offsetAmount;\n return;\n }\n\n if (!offsetElement) { calculatedOffset.value = 0; return; }\n\n try {\n const element = document.querySelector(offsetElement);\n if (!element) { calculatedOffset.value = 0; return; }\n\n const rect = element.getBoundingClientRect();\n const dim = direction.value === 'row' ? rect.height : rect.width;\n calculatedOffset.value = dim;\n } catch (error) {\n console.warn('[resizable] Failed to measure offset element:', error);\n calculatedOffset.value = 0;\n }\n }\n\n // ── Computed styles — logical properties rotate with writing-mode ──\n\n const handleStyles = computed(() => {\n const styles: Record<string, string> = {};\n if (calculatedOffset.value <= 0) return styles;\n const px = `${calculatedOffset.value}px`;\n if (offsetDirection === 'start' || offsetDirection === 'both') styles.insetBlockStart = px;\n if (offsetDirection === 'end' || offsetDirection === 'both') styles.insetBlockEnd = px;\n return styles;\n });\n\n const contentStyles = computed(() => {\n const styles: Record<string, string> = {};\n if (calculatedOffset.value <= 0) return styles;\n const px = `${calculatedOffset.value}px`;\n if (offsetDirection === 'start' || offsetDirection === 'both') styles.paddingBlockStart = px;\n if (offsetDirection === 'end' || offsetDirection === 'both') styles.paddingBlockEnd = px;\n return styles;\n });\n\n onMounted(() => { updateOffset(); });\n\n return { calculatedOffset, updateOffset, handleStyles, contentStyles };\n}\n","<template>\n <div\n ref=\"containerRef\"\n :class=\"[\n 'd-resizable',\n `d-resizable--${currentDirection}`,\n { 'd-resizable--resizing': isResizing },\n props.class,\n ]\"\n :data-storage-key=\"props.storageKey || undefined\"\n >\n <!-- @slot Container for panels and handles. -->\n <slot\n :panels=\"group.syncedPanels.value\"\n :direction=\"currentDirection\"\n :is-resizing=\"isResizing\"\n :space-allocation-strategy=\"props.spaceAllocationStrategy\"\n :resize-panel=\"resizePanel\"\n :collapse-panel=\"collapsePanel\"\n :start-resize=\"startResize\"\n :stop-resize=\"stopResize\"\n />\n </div>\n</template>\n\n<script setup>\nimport {\n ref,\n computed,\n watch,\n onUnmounted,\n provide,\n} from 'vue';\nimport { RESIZABLE_CONTEXT_KEY, buildHandleId } from './resizable_constants';\nimport {\n useResizablePanelControls,\n useResizableGroup,\n useResizeHandling,\n checkAutoCollapseRules,\n useResizableAnnouncements,\n useResizableOffset,\n} from './composables';\nimport { useResizableDrag } from './composables/useResizableDrag';\n\nconst props = defineProps({\n /**\n * Layout direction. 'row' for horizontal, 'column' for vertical.\n * @values 'row', 'column'\n */\n direction: {\n type: String,\n default: 'row',\n },\n /** localStorage key for persisting panel sizes across page loads. */\n storageKey: {\n type: String,\n default: null,\n },\n /** Additional CSS classes applied to the container element. */\n class: {\n type: [String, Object, Array],\n default: '',\n },\n /**\n * Panel configurations array. When provided, panels are initialized\n * from this array instead of registering via child DtResizablePanel components.\n */\n panels: {\n type: Array,\n default: () => [],\n },\n /**\n * Strategy for redistributing space when panels open/close.\n * @values 'proportional', 'preserve-manual'\n */\n spaceAllocationStrategy: {\n type: String,\n default: 'proportional',\n validator: (val) => ['proportional', 'preserve-manual'].includes(val),\n },\n /** Rules defining which panels collapse first when space is constrained */\n collapseRules: {\n type: Array,\n default: () => [],\n },\n /** Custom storage adapter. Overrides storageKey when both are provided. */\n storage: {\n type: Object,\n default: null,\n },\n /** CSS selector for a fixed element to offset handles and panel content from. */\n offsetElement: { type: String, default: null },\n /** Explicit pixel offset. Overrides offsetElement measurement when both provided. */\n offsetAmount: { type: Number, default: null },\n /**\n * Which edge(s) the offset applies to.\n * @values 'start', 'end', 'both'\n */\n offsetDirection: { type: String, default: 'start' },\n /**\n * i18n message overrides for screen reader announcements.\n * Accepts keys from ResizableKeyboardMessages.\n */\n messages: {\n type: Object,\n default: () => ({}),\n },\n});\n\nconst emit = defineEmits(\n /**\n * @event panel-resize - Emitted when a panel is resized. Payload: (panelId, size).\n * @event panel-collapse - Emitted when a panel collapses or expands. Payload: (panelId, collapsed).\n * @event resize-start - Emitted when a resize drag begins. Payload: (handleId).\n * @event resize-end - Emitted when a resize drag ends. Payload: (handleId).\n */\n ['panel-resize', 'panel-collapse', 'resize-start', 'resize-end'],\n);\n\nconst containerRef = ref(null);\n\nconst currentDirection = computed(() => props.direction);\n\n// Note: storageKey and storage are captured at mount time. If they need to\n// change dynamically in the future, useResizableGroup should accept refs.\nconst group = useResizableGroup({\n storageKey: props.storageKey ?? null,\n direction: currentDirection,\n containerRef,\n storageAdapter: props.storage ?? undefined,\n});\n\nconst isResizing = ref(false);\nconst activeHandleId = ref(undefined);\n\nconst resizeHandler = useResizeHandling(() => group.containerSize.value);\n\nconst isInitializing = group.isInitializing;\nconst registerPanel = (config) => group.registerPanel(config);\nconst unregisterPanel = (id) => group.unregisterPanel(id);\nconst saveToStorage = (panels) => group.saveCurrentLayout(panels);\n\nconst {\n commitPanelSize,\n resizePanel,\n collapsePanel,\n resetPanels: originalResetPanels,\n processAutoCollapseExpand,\n} = useResizablePanelControls({\n panels: group.syncedPanels,\n containerSize: group.containerSize,\n containerRef,\n onPanelResize: (panelId, size) => emit('panel-resize', panelId, size),\n onPanelCollapse: (panelId, collapsed) => emit('panel-collapse', panelId, collapsed),\n updateSavedPanel: (panelId, updates) => group.updateSavedPanel(panelId, updates),\n});\n\nfunction resetPanels (beforePanelId, afterPanelId, behavior = 'all') {\n originalResetPanels(beforePanelId, afterPanelId, behavior);\n\n if (behavior === 'all') {\n group.syncedPanels.value.forEach(p => group.updateSavedPanel(p.id, { manualTargetRatio: undefined }));\n group.clearSavedState();\n } else {\n if (beforePanelId) group.updateSavedPanel(beforePanelId, { manualTargetRatio: undefined });\n if (afterPanelId) group.updateSavedPanel(afterPanelId, { manualTargetRatio: undefined });\n }\n}\n\nfunction processAutoCollapse () {\n processAutoCollapseExpand();\n if (!props.collapseRules?.length) return;\n const panels = group.syncedPanels.value;\n const panelsToCollapse = checkAutoCollapseRules(panels, props.collapseRules, group.containerSize.value);\n if (panelsToCollapse.length === 0) return;\n const panel = panels.find(p => p.id === panelsToCollapse[0]);\n if (panel && !panel.collapsed) collapsePanel(panelsToCollapse[0], true);\n}\n\nconst { announce } = useResizableAnnouncements();\n\nconst offset = useResizableOffset({\n offsetElement: props.offsetElement,\n offsetAmount: props.offsetAmount,\n offsetDirection: props.offsetDirection,\n direction: currentDirection,\n});\n\nconst handleInstances = new Set();\nfunction registerHandle (inst) { handleInstances.add(inst); }\nfunction unregisterHandle (inst) { handleInstances.delete(inst); }\n\nconst drag = useResizableDrag({\n direction: currentDirection,\n containerRef,\n panels: group.syncedPanels,\n containerSize: group.containerSize,\n resizeHandler,\n onDragStart (handleId) {\n isResizing.value = true;\n activeHandleId.value = handleId;\n emit('resize-start', handleId);\n },\n onDragEnd (beforePanelId, afterPanelId, beforeSize, afterSize, sizesChanged) {\n const handleId = drag.dragState.handleId ?? buildHandleId(beforePanelId, afterPanelId);\n isResizing.value = false;\n activeHandleId.value = undefined;\n\n if (sizesChanged) {\n commitPanelSize(beforePanelId, beforeSize);\n commitPanelSize(afterPanelId, afterSize);\n\n emit('resize-end', handleId);\n processAutoCollapse();\n }\n },\n});\n\nfunction startResize (handleId) { drag.startDrag(handleId); }\nfunction stopResize () { drag.cancelDrag(); }\nfunction savePanelsToStorage () { saveToStorage(group.syncedPanels.value); }\nfunction emitPanelResize (panelId, size) { emit('panel-resize', panelId, size); }\n\nwatch(group.syncedPanels, (panels) => {\n if (panels.length > 0 && !isInitializing.value) {\n processAutoCollapse();\n }\n}, { flush: 'post' });\n\nonUnmounted(() => {\n group.disconnectObserver();\n drag.cancelDrag();\n});\n\n// Provide single context object for child components\nprovide(RESIZABLE_CONTEXT_KEY, {\n layout: group.layout,\n panels: group.syncedPanels,\n panelMap: group.panelMap,\n direction: currentDirection,\n containerSize: group.containerSize,\n containerElement: computed(() => containerRef.value),\n isResizing: computed(() => isResizing.value),\n activeHandleId: computed(() => activeHandleId.value),\n isInitializing: computed(() => isInitializing.value),\n messages: props.messages,\n startResize: (handleId) => startResize(handleId),\n resetPanels,\n registerHandle,\n unregisterHandle,\n registerPanel,\n unregisterPanel,\n saveToStorage: savePanelsToStorage,\n announce,\n offsetHandleStyles: offset.handleStyles,\n offsetContentStyles: offset.contentStyles,\n collapsePanel,\n emitPanelResize,\n commitPanelSize,\n updateSavedPanel: (panelId, updates) => group.updateSavedPanel(panelId, updates),\n});\n\n// Expose methods for programmatic control\ndefineExpose({\n resizePanel,\n collapsePanel,\n resetPanels,\n state: computed(() => ({\n direction: currentDirection.value,\n panels: group.syncedPanels.value,\n containerSize: group.containerSize.value,\n isResizing: isResizing.value,\n activeHandleId: activeHandleId.value,\n })),\n panelConfigs: computed(() => props.panels),\n allocationStrategy: computed(() => props.spaceAllocationStrategy),\n});\n</script>\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ require(`./chunk-Bmb41Sf3.cjs`);const e=require(`./resizable_utils-DhuzXRdP.cjs`),t=require(`./useResizableCalculations-BDITle3Q.cjs`);let n=require(`vue`);function r(e,n,r,i=`user`){let a=t.n(e,r);return e.userMinSizePixels=a.userMinSizePixels,e.userMaxSizePixels=a.userMaxSizePixels,e.systemMinSizePixels=a.systemMinSizePixels,e.systemMaxSizePixels=a.systemMaxSizePixels,e.collapseSizePixels=a.collapseSizePixels,t.r(n,a,i)}function i(e,t){return e.resizable!==!1&&!e.collapsed&&t.resizable!==!1&&!t.collapsed}function a(t){let{panels:n,containerSize:a,containerRef:o,onPanelResize:s,onPanelCollapse:c,updateSavedPanel:l}=t,u=new Map;function d(t){return e.o(t,a.value)}function f(e){let{panelId:t,action:r,source:i}=e,a=n.value.find(e=>e.id===t),s=r===`collapse`;return p(t,a,s)||(s?m(a,i):h(a),c(t,s),o.value&&o.value.dispatchEvent(new CustomEvent(`panels-updated`)),{success:!0,panelId:t,newState:s?`collapsed`:`expanded`})}function p(e,t,n){if(!t)return{success:!1,reason:`Panel not found`,panelId:e,newState:`unchanged`};let r=t.collapsed;if(n&&r)return{success:!0,reason:`Already collapsed`,panelId:e,newState:`unchanged`};if(!n&&!r)return{success:!0,reason:`Already expanded`,panelId:e,newState:`unchanged`};if(n&&!t.collapsible)return{success:!1,reason:`Panel is not collapsible`,panelId:e,newState:`unchanged`}}function m(e,t){let r={sizes:new Map,manualTargets:new Map,containerSize:a.value};n.value.forEach(e=>{r.sizes.set(e.id,e.pixelSize),r.manualTargets.set(e.id,e.manualTargetSize)}),u.set(e.id,r),l(e.id,{collapsed:!0,autoCollapsed:t===`system`}),n.value.forEach(t=>{t.id!==e.id&&!t.collapsed&&l(t.id,{manualTargetRatio:void 0})})}function h(t){let i=t.autoCollapsed??!1,o=u.get(t.id);if(o){if(!(Math.abs(a.value-o.containerSize)/o.containerSize>.1)||!i){let e=o.sizes.get(t.id);e===void 0?l(t.id,{collapsed:!1,autoCollapsed:void 0}):l(t.id,{pixelSize:e,collapsed:!1,autoCollapsed:void 0}),n.value.forEach(e=>{if(e.id===t.id)return;let n=o.sizes.get(e.id),r=o.manualTargets.get(e.id)!==void 0,i=e.manualTargetSize!==void 0;!r&&!i&&n!==void 0&&l(e.id,{pixelSize:n})})}else l(t.id,{collapsed:!1,autoCollapsed:void 0});u.delete(t.id)}else{let n=r(t,e.o(t.initialSize??`50p`,a.value),a.value,`system`);l(t.id,{pixelSize:n,collapsed:!1,autoCollapsed:void 0})}}function g(e,t){let n=Math.round(t),r=a.value;l(e,{pixelSize:n,manualTargetRatio:r>0?n/r:void 0})}function _(e,t){let i=n.value.find(t=>t.id===e);if(!i||i.collapsed)return;let o=r(i,t,a.value);g(e,o),s(e,o)}function v(e,t,n){let r=n?.isAutoCollapse?`system`:`prop`;f({panelId:e,action:t?`collapse`:`expand`,source:r})}function y(e,t){let n=e.pixelSize+t.pixelSize,r=d(e.initialSize||`50p`),i=r+d(t.initialSize||`50p`),a=Math.round(i>0?r/i*n:n/2),o=n-a;l(e.id,{pixelSize:a,manualTargetRatio:void 0}),l(t.id,{pixelSize:o,manualTargetRatio:void 0}),s(e.id,a),s(t.id,o)}function b(){for(let e=0;e<n.value.length-1;e++){let t=n.value[e],r=n.value[e+1];i(t,r)&&y(t,r)}}function x(e,t){let r=e?n.value.find(t=>t.id===e):void 0,a=t?n.value.find(e=>e.id===t):void 0;r&&a&&i(r,a)&&y(r,a)}function S(e){if(!e)return;let t=n.value.find(t=>t.id===e);if(!t||t.collapsed||t.resizable===!1)return;let r=d(t.initialSize||`50p`),i=r-t.pixelSize,a=n.value.indexOf(t),o=n.value.find((e,t)=>t!==a&&!e.collapsed&&e.resizable!==!1);if(!o)return;let c=o.pixelSize-i;l(t.id,{pixelSize:r,manualTargetRatio:void 0}),l(o.id,{pixelSize:c}),s(t.id,r),s(o.id,c)}function C(e,t,n=`all`){try{n===`all`?b():n===`before`?S(e):n===`after`?S(t):x(e,t)}catch(e){console.error(`[resizable] Error in resetPanels:`,e)}}function w(){let e=[],t=a.value;for(let r of n.value)r.collapsed||!r.collapsible||!r.collapseSizePixels||t<r.collapseSizePixels&&f({panelId:r.id,action:`collapse`,source:`system`}).newState===`collapsed`&&e.push(r.id);return e}function T(){let e=[],t=a.value;for(let r of n.value)!r.collapsed||!r.autoCollapsed||!r.collapseSizePixels||t>=r.collapseSizePixels&&f({panelId:r.id,action:`expand`,source:`system`}).newState===`expanded`&&e.push(r.id);return e}function E(){let e=T();return{collapsed:w(),expanded:e}}return{commitPanelSize:g,resizePanel:_,collapsePanel:v,resetPanels:C,processCollapseRequest:f,checkAutoCollapse:w,checkAutoExpand:T,processAutoCollapseExpand:E}}function o(e){if(!e||e.length===0)return[];let t=e.map((e,t)=>({rule:e,index:t}));return t.sort((e,t)=>{let n=e.rule.priority-t.rule.priority;return n===0?e.index-t.index:n}),t.map(e=>e.rule)}function s(t,n,r){return n.minSizeBeforeCollapse===void 0?t.userMinSizePixels:e.o(n.minSizeBeforeCollapse,r)}function c(e,t,n){let r=e.find(e=>e.id===t.panelId);if(!r||r.collapsed)return;let i=s(r,t,n);if(i!==void 0)return r.pixelSize<=i?r.id:void 0}function l(e,t,n){return!e||e.length===0||!t||t.length===0?[]:o(t).map(t=>c(e,t,n)).filter(e=>e!==void 0)}function u(t,n,r){if(r!==void 0){let i=r.pixelSize;return!isFinite(i)||i<0||n>0&&i>n*2?e.o(t.initialSize??`50p`,n):i}return e.o(t.initialSize??`50p`,n)}function d(e,t){return t!==void 0&&t.collapsed!==void 0?t.collapsed:!!e.collapsed}function f(e,n,r=`system`){let i=t.r(e,n,r);return{clamped:i,delta:i-e}}function p(e){if(e)return new Map(e.map(e=>[e.id,e]))}function m(e,n,r){return e.map(e=>{let i=t.n(e,n),a=r?.get(e.id),o=d(e,a),s=e.resizable===!1,c=a?.manualTargetRatio,l;return l=o?0:c!==void 0&&n>0?c*n:u(e,n,a),{config:e,constraints:i,width:l,collapsed:o,isFixed:s,manualTargetRatio:c}})}function h(e,t){let n=0;for(let t of e)if(t.isFixed){let{clamped:e}=f(t.width,t.constraints);t.width=e,n+=e}let r=e.filter(e=>!e.isFixed&&e.manualTargetRatio!==void 0);for(let e of r){let{clamped:r}=f((e.manualTargetRatio??0)*t,e.constraints,`user`);e.width=r,n+=r}return n}function g(e){let t=e.length+1;for(let n=0;n<t;n++){let t=0,n=new Set;for(let r of e){let{clamped:e,delta:i}=f(r.width,r.constraints);i!==0&&(r.width=e,n.add(r.config.id),t+=i)}if(t===0)break;let r=e.filter(e=>!n.has(e.config.id));if(r.length===0)break;let i=-t/r.length;for(let e of r)e.width+=i}for(let t of e){let{clamped:e}=f(t.width,t.constraints);t.width=e}}function _(e,t,n){let r=n-e.reduce((e,t)=>e+t.width,0);if(r>1){let e=[...t].reverse().find(e=>!e.isFixed);e&&(e.width+=r)}}function v(e,t){if(t<=0){e.forEach(e=>{e.collapsed||(e.width=0)});return}let n=e.filter(e=>!e.collapsed);if(n.length===0)return;let r=h(n,t),i=n.filter(e=>!e.isFixed&&e.manualTargetRatio===void 0),a=Math.max(0,t-r);if(i.length===0)return;let o=i.reduce((e,t)=>e+Math.max(0,t.width),0);for(let e of i)o>0?e.width=e.width/o*a:e.width=a/i.length;g(i),_(n,i,t)}function y(e,t){e.sort((e,t)=>t.remainder-e.remainder);let n=t;for(let{panel:t}of e){if(n<=0)break;let e=t.constraints.systemMaxSizePixels??t.constraints.userMaxSizePixels??1/0;t.width<e&&!t.isFixed&&(t.width+=1,--n)}}function b(e,t){if(t<=0)return;let n=e.filter(e=>!e.collapsed);if(n.length===0)return;let r=[];for(let e of n){let t=Math.floor(e.width);r.push({panel:e,remainder:e.width-t}),e.width=t}y(r,t-n.reduce((e,t)=>e+t.width,0))}function x(e,t){let n=new Map,r=0;for(let i of e){let e=i.collapsed?0:i.width,a=r,o=Math.max(0,t-a-e);n.set(i.config.id,{id:i.config.id,left:a,right:o,width:e,collapsed:i.collapsed,constraints:i.constraints}),r+=e}return n}function S(t,n){let r=[];for(let i=0;i<t.length-1;i++){let a=t[i],o=t[i+1];if(a.resizable===!1||o.resizable===!1)continue;let s=n.get(a.id),c=n.get(o.id);if(!s||!c)continue;let l=s.collapsed||c.collapsed;r.push({id:e.f(a.id,o.id),beforePanelId:a.id,afterPanelId:o.id,left:s.left+s.width,disabled:l})}return r}function C(e){let{panels:t,containerSize:n,savedState:r}=e;if(t.length===0)return{panels:new Map,handles:[]};let i=m(t,n,p(r));v(i,n),b(i,n);let a=x(i,n);return{panels:a,handles:S(t,a)}}function w(e){return typeof e.id==`string`&&typeof e.pixelSize==`number`&&e.pixelSize>=0}function T(e){return(e.collapsed===void 0||typeof e.collapsed==`boolean`)&&(e.autoCollapsed===void 0||typeof e.autoCollapsed==`boolean`)}function E(e){if(typeof e!=`object`||!e)return!1;let t=e;return w(t)&&T(t)}function D(e){return Array.isArray(e)&&e.every(e=>E(e))}function O(e){return{save(t){try{localStorage.setItem(e,JSON.stringify(t))}catch(e){console.error(`[resizable] Failed to save to localStorage:`,e)}},load(){try{let t=localStorage.getItem(e);if(!t)return null;let n;try{n=JSON.parse(t)}catch{return localStorage.removeItem(e),null}return D(n)?n:(localStorage.removeItem(e),null)}catch(t){console.warn(`[resizable] Failed to load from localStorage:`,t);try{localStorage.removeItem(e)}catch{}return null}},clear(){try{localStorage.removeItem(e)}catch{}}}}function k(e,t){let n=t??(e?O(e):null);function r(e){if(!n)return;let t=e.map(e=>({id:e.id,pixelSize:e.pixelSize,collapsed:e.collapsed,autoCollapsed:e.autoCollapsed}));n.save(t)}function i(){if(!n)return null;let e=n.load();return e?D(e)?e:(n.clear(),null):null}function a(e,t){e.restoredFromStorage||(t.pixelSize!==void 0&&(e.pixelSize=t.pixelSize),t.collapsed!==void 0&&(e.collapsed=t.collapsed),t.autoCollapsed!==void 0&&(e.autoCollapsed=t.autoCollapsed),e.restoredFromStorage=!0)}function o(e){let t=i();if(!t)return!1;let r=new Set(e.map(e=>e.id)),o=new Set(t.map(e=>e.id));return Array.from(r).some(e=>!o.has(e))?(n&&n.clear(),!1):(t.forEach(t=>{let n=e.find(e=>e.id===t.id);n&&a(n,t)}),!0)}function s(){n&&n.clear()}return{saveToStorage:r,loadFromStorage:i,loadFromStorageWithValidation:o,restorePanelFromStorage:a,clearStorage:s}}var A=e.c;function j(e,n,r,i){let a=r.panels.get(e.id),o=a?.constraints??t.n(e,n),s=a?.width??0,c=a?.collapsed??!!e.collapsed;return{...e,pixelSize:s,collapsed:c,userMinSizePixels:o.userMinSizePixels,userMaxSizePixels:o.userMaxSizePixels,systemMinSizePixels:o.systemMinSizePixels,systemMaxSizePixels:o.systemMaxSizePixels,collapseSizePixels:o.collapseSizePixels,manualTargetRatio:i?.manualTargetRatio,autoCollapsed:i?.autoCollapsed}}function M(e){let{storageKey:t,direction:r,containerRef:i}=e,a=(0,n.ref)([]),o=(0,n.ref)(0),s=k(t,e.storageAdapter),c=(0,n.ref)(s.loadFromStorage()),l=(0,n.ref)(!0),u=(0,n.computed)(()=>{let e=a.value,t=o.value;return e.length===0||t<=0?{panels:new Map,handles:[]}:C({panels:e,containerSize:t,savedState:c.value??void 0})}),d=(0,n.computed)(()=>{let e=u.value,t=o.value,n=new Map(c.value?.map(e=>[e.id,e])??[]);return a.value.map(r=>j(r,t,e,n.get(r.id)))});(0,n.watch)(u,e=>{e.panels.size>0&&l.value&&(l.value=!1)},{immediate:!0});let f=(0,n.computed)(()=>{let e=new Map;for(let t of d.value)e.set(t.id,t);return e}),p=!1;function m(e){e.id.includes(`:`)&&console.warn(`[resizable] Panel id "${e.id}" contains ':' which is reserved as the handle separator. Use kebab-case.`);let t=a.value.findIndex(t=>t.id===e.id);t===-1?(a.value=[...a.value,e],p||(p=!0,(0,n.nextTick)(()=>{a.value=h(a.value),p=!1}))):a.value=a.value.map((n,r)=>r===t?e:n)}function h(e){let t=i.value;if(!t)return e;let n=Array.from(t.querySelectorAll(`.d-resizable-panel[data-panel-id]`));if(n.length===0)return e;let r=new Map;return n.forEach((e,t)=>{let n=e.getAttribute(`data-panel-id`);n&&r.set(n,t)}),[...e].sort((e,t)=>(r.get(e.id)??1/0)-(r.get(t.id)??1/0))}function g(e){a.value=a.value.filter(t=>t.id!==e)}function _(e){s.saveToStorage(e),c.value=e.map(e=>({id:e.id,pixelSize:e.pixelSize,collapsed:e.collapsed,autoCollapsed:e.autoCollapsed,manualTargetRatio:e.manualTargetRatio}))}function v(e,t){c.value||(c.value=[]);let n=c.value.findIndex(t=>t.id===e);if(n>=0)c.value[n]={...c.value[n],...t};else{let n=d.value.find(t=>t.id===e)?.pixelSize??0;c.value.push({id:e,pixelSize:n,...t})}c.value=[...c.value],s.saveToStorage(c.value)}function y(){c.value=s.loadFromStorage()}function b(){s.clearStorage(),c.value=null}let x=new ResizeObserver(e=>{for(let t of e){let e=r.value===`row`?t.contentRect.width:t.contentRect.height;o.value=A(Math.round(e))}});function S(){x.disconnect()}return(0,n.watch)(i,(e,t)=>{t&&x.unobserve(t),e&&(o.value=A(r.value===`row`?e.clientWidth:e.clientHeight),x.observe(e))},{immediate:!0}),{layout:u,syncedPanels:d,panelMap:f,containerSize:o,isInitializing:l,registerPanel:m,unregisterPanel:g,saveCurrentLayout:_,updateSavedPanel:v,reloadFromStorage:y,clearSavedState:b,disconnectObserver:S}}var N={isActive:!1,handleId:null,beforePanelId:null,afterPanelId:null,proposedBeforeSize:0,proposedAfterSize:0};function P(e,t){return e.querySelector(`[data-panel-id="${t}"]`)}function F(e,t){return e.querySelector(`[data-handle-id="${t}"]`)}function I(e,t,n){e.style.insetInlineStart=`${t}px`,e.style.insetInlineEnd=`${n}px`,e.style.inlineSize=``}function L(e){e.style.insetInlineStart=``,e.style.insetInlineEnd=``,e.style.inlineSize=``}function R(e,t){e.style.insetInlineStart=`${Math.max(0,t)}px`}function z(e){e.style.insetInlineStart=``}function B(e,t){let n=e.indexOf(`:`);if(n===-1)return{beforePanel:null,afterPanel:null};let r=e.slice(0,n),i=e.slice(n+1);return{beforePanel:t.find(e=>e.id===r)??null,afterPanel:t.find(e=>e.id===i)??null}}function V(e){let{direction:t,containerRef:r,panels:i,containerSize:a,resizeHandler:o,onDragEnd:s,onDragStart:c}=e,l=(0,n.reactive)({...N}),u=null,d=null,f=null,p=null,m=null,h=0,g=0,_=0,v=null,y=null,b=null;function x(){y=e=>O(e),b=()=>k(),document.addEventListener(`pointermove`,y),document.addEventListener(`pointerup`,b),document.addEventListener(`pointercancel`,b),document.addEventListener(`keydown`,j)}function S(){y&&(document.removeEventListener(`pointermove`,y),y=null),b&&(document.removeEventListener(`pointerup`,b),document.removeEventListener(`pointercancel`,b),b=null),document.removeEventListener(`keydown`,j)}function C(){S(),document.body.style.userSelect=``,document.body.style.cursor=``,Object.assign(l,N),u=null,d=null,f=null,p=null,m=null,h=0,g=0,_=0,v=null}function w(e,t,n){let{beforePanel:r,afterPanel:i}=B(t,n);if(!r||!i)return console.warn(`[resizable] No panel pair found for handle "${t}"`),null;let a=P(e,r.id),o=P(e,i.id),s=F(e,t);return!a||!o?(console.warn(`[resizable] Panel element(s) not found for handle "${t}"`),null):{beforePanel:r,afterPanel:i,beforeEl:a,afterEl:o,handleElement:s}}function T(e){let n=r.value;if(!n)return;let a=w(n,e,i.value);a&&(u=a.beforeEl,d=a.afterEl,f=a.handleElement,p=a.beforePanel,m=a.afterPanel,h=a.beforePanel.pixelSize,g=a.afterPanel.pixelSize,_=parseFloat(u.style.insetInlineStart||`0`),v=n.getBoundingClientRect(),Object.assign(l,{isActive:!0,handleId:e,beforePanelId:a.beforePanel.id,afterPanelId:a.afterPanel.id,proposedBeforeSize:h,proposedAfterSize:g}),document.body.style.userSelect=`none`,document.body.style.cursor=t.value===`row`?`ew-resize`:`ns-resize`,x(),c?.(e))}function E(e,t){let n=v;return t===`row`?e.clientX-n.left:e.clientY-n.top}function D(){return l.isActive&&!!r.value&&!!u&&!!d&&!!l.handleId&&!!p&&!!m}function O(e){if(!D())return;let n=E(e,t.value),r=o.processResizeMove(n,p,m,a.value,l.handleId,i.value,_);if(!r.isValidResize)return;l.proposedBeforeSize!==r.beforePanelSize&&(l.proposedBeforeSize=r.beforePanelSize),l.proposedAfterSize!==r.afterPanelSize&&(l.proposedAfterSize=r.afterPanelSize);let s=a.value,c=r.constrainedCursorPosition,h=s-c,g=c-2,v=s-c-r.afterPanelSize;I(u,_,h),I(d,c,Math.max(0,v)),f&&R(f,g)}function k(){if(!l.isActive)return;let e=l.beforePanelId,t=l.afterPanelId,n=l.proposedBeforeSize,r=l.proposedAfterSize,i=h,a=g;u&&L(u),d&&L(d),f&&z(f),C(),e&&t&&s(e,t,n,r,n!==i||r!==a)}function A(){l.isActive&&(u&&d&&(L(u),L(d)),f&&z(f),C())}function j(e){e.key===`Escape`&&l.isActive&&(e.preventDefault(),A())}return(0,n.onUnmounted)(()=>{A()}),{dragState:l,startDrag:T,onDragMove:O,commitDrag:k,cancelDrag:A,cleanup:C}}var H=null,U,W=0;function G(){return H||(H=document.getElementById(`d-resizable-announcements`),H||(H=document.createElement(`div`),H.id=`d-resizable-announcements`,H.setAttribute(`aria-live`,`polite`),H.setAttribute(`aria-atomic`,`true`),H.style.position=`absolute`,H.style.left=`-10000px`,H.style.width=`1px`,H.style.height=`1px`,H.style.overflow=`hidden`,document.body.appendChild(H))),H}function K(e){if(!e.trim())return;U&&clearTimeout(U);let t=G();t.textContent=``,U=setTimeout(()=>{t.textContent=e,setTimeout(()=>{t.textContent=``},1e3)},100)}function q(){return(0,n.onMounted)(()=>{W++,G()}),(0,n.onUnmounted)(()=>{U&&clearTimeout(U),W--,W<=0&&H&&(H.remove(),H=null,W=0)}),{announce:K}}function J(e={}){let{offsetElement:t=null,offsetAmount:r=null,offsetDirection:i=`start`,direction:a=(0,n.ref)(`row`)}=e,o=(0,n.ref)(0);function s(){if(r!=null&&r>0){o.value=r;return}if(!t){o.value=0;return}try{let e=document.querySelector(t);if(!e){o.value=0;return}let n=e.getBoundingClientRect();o.value=a.value===`row`?n.height:n.width}catch(e){console.warn(`[resizable] Failed to measure offset element:`,e),o.value=0}}let c=(0,n.computed)(()=>{let e={};if(o.value<=0)return e;let t=`${o.value}px`;return(i===`start`||i===`both`)&&(e.insetBlockStart=t),(i===`end`||i===`both`)&&(e.insetBlockEnd=t),e}),l=(0,n.computed)(()=>{let e={};if(o.value<=0)return e;let t=`${o.value}px`;return(i===`start`||i===`both`)&&(e.paddingBlockStart=t),(i===`end`||i===`both`)&&(e.paddingBlockEnd=t),e});return(0,n.onMounted)(()=>{s()}),{calculatedOffset:o,updateOffset:s,handleStyles:c,contentStyles:l}}var Y=[`data-storage-key`],X={__name:`resizable`,props:{direction:{type:String,default:`row`},storageKey:{type:String,default:null},class:{type:[String,Object,Array],default:``},panels:{type:Array,default:()=>[]},spaceAllocationStrategy:{type:String,default:`proportional`,validator:e=>[`proportional`,`preserve-manual`].includes(e)},collapseRules:{type:Array,default:()=>[]},storage:{type:Object,default:null},offsetElement:{type:String,default:null},offsetAmount:{type:Number,default:null},offsetDirection:{type:String,default:`start`},messages:{type:Object,default:()=>({})}},emits:[`panel-resize`,`panel-collapse`,`resize-start`,`resize-end`],setup(r,{expose:i,emit:o}){let s=r,c=o,u=(0,n.ref)(null),d=(0,n.computed)(()=>s.direction),f=M({storageKey:s.storageKey??null,direction:d,containerRef:u,storageAdapter:s.storage??void 0}),p=(0,n.ref)(!1),m=(0,n.ref)(void 0),h=t.t(()=>f.containerSize.value),g=f.isInitializing,_=e=>f.registerPanel(e),v=e=>f.unregisterPanel(e),y=e=>f.saveCurrentLayout(e),{commitPanelSize:b,resizePanel:x,collapsePanel:S,resetPanels:C,processAutoCollapseExpand:w}=a({panels:f.syncedPanels,containerSize:f.containerSize,containerRef:u,onPanelResize:(e,t)=>c(`panel-resize`,e,t),onPanelCollapse:(e,t)=>c(`panel-collapse`,e,t),updateSavedPanel:(e,t)=>f.updateSavedPanel(e,t)});function T(e,t,n=`all`){C(e,t,n),n===`all`?(f.syncedPanels.value.forEach(e=>f.updateSavedPanel(e.id,{manualTargetRatio:void 0})),f.clearSavedState()):(e&&f.updateSavedPanel(e,{manualTargetRatio:void 0}),t&&f.updateSavedPanel(t,{manualTargetRatio:void 0}))}function E(){if(w(),!s.collapseRules?.length)return;let e=f.syncedPanels.value,t=l(e,s.collapseRules,f.containerSize.value);if(t.length===0)return;let n=e.find(e=>e.id===t[0]);n&&!n.collapsed&&S(t[0],!0)}let{announce:D}=q(),O=J({offsetElement:s.offsetElement,offsetAmount:s.offsetAmount,offsetDirection:s.offsetDirection,direction:d}),k=new Set;function A(e){k.add(e)}function j(e){k.delete(e)}let N=V({direction:d,containerRef:u,panels:f.syncedPanels,containerSize:f.containerSize,resizeHandler:h,onDragStart(e){p.value=!0,m.value=e,c(`resize-start`,e)},onDragEnd(t,n,r,i,a){let o=N.dragState.handleId??e.f(t,n);p.value=!1,m.value=void 0,a&&(b(t,r),b(n,i),c(`resize-end`,o),E())}});function P(e){N.startDrag(e)}function F(){N.cancelDrag()}function I(){y(f.syncedPanels.value)}function L(e,t){c(`panel-resize`,e,t)}return(0,n.watch)(f.syncedPanels,e=>{e.length>0&&!g.value&&E()},{flush:`post`}),(0,n.onUnmounted)(()=>{f.disconnectObserver(),N.cancelDrag()}),(0,n.provide)(e.d,{layout:f.layout,panels:f.syncedPanels,panelMap:f.panelMap,direction:d,containerSize:f.containerSize,containerElement:(0,n.computed)(()=>u.value),isResizing:(0,n.computed)(()=>p.value),activeHandleId:(0,n.computed)(()=>m.value),isInitializing:(0,n.computed)(()=>g.value),messages:s.messages,startResize:e=>P(e),resetPanels:T,registerHandle:A,unregisterHandle:j,registerPanel:_,unregisterPanel:v,saveToStorage:I,announce:D,offsetHandleStyles:O.handleStyles,offsetContentStyles:O.contentStyles,collapsePanel:S,emitPanelResize:L,commitPanelSize:b,updateSavedPanel:(e,t)=>f.updateSavedPanel(e,t)}),i({resizePanel:x,collapsePanel:S,resetPanels:T,state:(0,n.computed)(()=>({direction:d.value,panels:f.syncedPanels.value,containerSize:f.containerSize.value,isResizing:p.value,activeHandleId:m.value})),panelConfigs:(0,n.computed)(()=>s.panels),allocationStrategy:(0,n.computed)(()=>s.spaceAllocationStrategy)}),(e,t)=>((0,n.openBlock)(),(0,n.createElementBlock)(`div`,{ref_key:`containerRef`,ref:u,class:(0,n.normalizeClass)([`d-resizable`,`d-resizable--${d.value}`,{"d-resizable--resizing":p.value},s.class]),"data-storage-key":s.storageKey||void 0},[(0,n.renderSlot)(e.$slots,`default`,{panels:(0,n.unref)(f).syncedPanels.value,direction:d.value,isResizing:p.value,spaceAllocationStrategy:s.spaceAllocationStrategy,resizePanel:(0,n.unref)(x),collapsePanel:(0,n.unref)(S),startResize:P,stopResize:F})],10,Y))}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return X}});
2
+ //# sourceMappingURL=resizable-aOVGO_Os.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resizable-aOVGO_Os.cjs","names":[],"sources":["../components/resizable/composables/useResizablePanelState.ts","../components/resizable/composables/useResizablePanelControls.ts","../components/resizable/composables/computeLayout.ts","../components/resizable/composables/useResizableStorage.ts","../components/resizable/composables/useResizableGroup.ts","../components/resizable/composables/useResizableDrag.ts","../components/resizable/composables/useResizableAnnouncements.ts","../components/resizable/composables/useResizableOffset.ts","../components/resizable/resizable.vue"],"sourcesContent":["/**\n * Panel State Model\n *\n * Pure functions for panel state creation, constraint calculation, and validation.\n * Single source of truth for all constraint-related logic.\n *\n * Constraint math has been extracted to constraintResolver.ts.\n */\n\nimport { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type { ResizablePanelConfig, ResizablePanelState } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { clampToTier } from './constraintResolver';\n\nimport { calculateConstraintHierarchy } from './constraintResolver';\n\n// Re-export constraint types and functions from constraintResolver\nexport type { ConstraintHierarchy } from './constraintResolver';\nexport { calculateConstraintHierarchy } from './constraintResolver';\n\n/**\n * Apply constraints to a pixel size for a panel.\n *\n * Updates panel's constraint pixel values and returns the constrained size.\n *\n * @param panel - Panel state to update constraints on\n * @param pixelSize - Desired pixel size before constraints\n * @param containerSize - Current container size in pixels\n * @param constraintType - Which constraints to apply: 'user' (default) or 'system'\n * @returns Constrained pixel size respecting bounds\n */\nexport function applyPanelPixelConstraints(\n panel: ResizablePanelState,\n pixelSize: number,\n containerSize: number,\n constraintType: 'user' | 'system' = 'user'\n): number {\n const constraints = calculateConstraintHierarchy(panel, containerSize);\n\n panel.userMinSizePixels = constraints.userMinSizePixels;\n panel.userMaxSizePixels = constraints.userMaxSizePixels;\n panel.systemMinSizePixels = constraints.systemMinSizePixels;\n panel.systemMaxSizePixels = constraints.systemMaxSizePixels;\n panel.collapseSizePixels = constraints.collapseSizePixels;\n\n return clampToTier(pixelSize, constraints, constraintType);\n}\n\n// ============================================================================\n// PANEL STATE CREATION\n// ============================================================================\n\nfunction applyConstraintsToSize(pixelSize: number, minSizePixels?: number, maxSizePixels?: number): number {\n let constrained = pixelSize;\n if (minSizePixels !== undefined) {\n constrained = Math.max(constrained, minSizePixels);\n }\n if (maxSizePixels !== undefined) {\n constrained = Math.min(constrained, maxSizePixels);\n }\n return constrained;\n}\n\nfunction derivePanelBehavioralState(\n panelConfig: ResizablePanelConfig,\n existingPanel?: ResizablePanelState\n): { collapsed: boolean; manualTargetSize: number | undefined } {\n return {\n collapsed: existingPanel?.collapsed ?? Boolean(panelConfig.collapsed),\n manualTargetSize: existingPanel?.manualTargetSize,\n };\n}\n\n/**\n * Create initial panel state from configuration.\n */\nexport function createPanelState(\n panelConfig: ResizablePanelConfig,\n containerSize: number,\n existingPanel?: ResizablePanelState\n): ResizablePanelState {\n const constraints = calculateConstraintHierarchy(panelConfig, containerSize);\n\n const rawPixelSize = parseSizeToPixels(panelConfig.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n const pixelSize = applyConstraintsToSize(rawPixelSize, constraints.userMinSizePixels, constraints.userMaxSizePixels);\n\n const behavioralState = derivePanelBehavioralState(panelConfig, existingPanel);\n const autoCollapsed = existingPanel?.autoCollapsed;\n\n return {\n ...panelConfig,\n pixelSize,\n ...behavioralState,\n userMinSizePixels: constraints.userMinSizePixels,\n userMaxSizePixels: constraints.userMaxSizePixels,\n systemMinSizePixels: constraints.systemMinSizePixels,\n systemMaxSizePixels: constraints.systemMaxSizePixels,\n collapseSizePixels: constraints.collapseSizePixels,\n autoCollapsed,\n };\n}\n\n/**\n * Create panel states for all panels in a configuration array.\n */\nexport function createBasicPanelStates(\n allPanels: ResizablePanelConfig[],\n containerSize: number,\n existingPanels?: ResizablePanelState[]\n): ResizablePanelState[] {\n return allPanels.map(panelConfig => {\n const existingPanel = existingPanels?.find(p => p.id === panelConfig.id);\n return createPanelState(panelConfig, containerSize, existingPanel);\n });\n}\n\n// ============================================================================\n// PANEL STATE VALIDATION\n// ============================================================================\n\n/**\n * Check if a panel pair should be skipped during constraint processing.\n */\nexport function shouldSkipPanelPair(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState): boolean {\n return (\n beforePanel.resizable === false ||\n !!beforePanel.collapsed ||\n afterPanel.resizable === false ||\n !!afterPanel.collapsed\n );\n}\n\n/**\n * Check if a panel pair can be reset to initial sizes.\n */\nexport function canResetPanelPair(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState): boolean {\n return (\n beforePanel.resizable !== false && !beforePanel.collapsed && afterPanel.resizable !== false && !afterPanel.collapsed\n );\n}\n","/**\n * Panel Controls Controller\n *\n * Operations for manipulating panel state: resize, collapse, reset.\n * Receives resizeHandler from Integration layer (single instance pattern).\n */\n\nimport type { Ref } from 'vue';\nimport { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type {\n ResizablePanelState,\n ResizableSizeValue,\n CollapseRule,\n} from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { applyPanelPixelConstraints, canResetPanelPair } from './useResizablePanelState';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * State snapshot captured before a panel is collapsed.\n */\nexport interface PreCollapseState {\n sizes: Map<string, number>;\n manualTargets: Map<string, number | undefined>;\n containerSize: number;\n}\n\nexport type CollapseRequestSource =\n | 'user'\n | 'system'\n | 'prop'\n | 'storage';\n\nexport interface CollapseRequest {\n panelId: string;\n action: 'collapse' | 'expand';\n source: CollapseRequestSource;\n}\n\nexport interface CollapseRequestResult {\n success: boolean;\n reason?: string;\n panelId: string;\n newState: 'collapsed' | 'expanded' | 'unchanged';\n}\n\nexport interface CollapseOptions {\n isAutoCollapse?: boolean;\n}\n\nexport interface ResizablePanelControlsOptions {\n panels: Ref<ResizablePanelState[]>;\n containerSize: Ref<number>;\n containerRef: Ref<HTMLElement | null>;\n onPanelResize: (panelId: string, pixelSize: number) => void;\n onPanelCollapse: (panelId: string, collapsed: boolean) => void;\n updateSavedPanel: (panelId: string, updates: Partial<import('./useResizableStorage').SavedPanelData>) => void;\n}\n\n// ============================================================================\n// MAIN COMPOSABLE\n// ============================================================================\n\nexport function useResizablePanelControls(options: ResizablePanelControlsOptions) {\n const {\n panels,\n containerSize,\n containerRef,\n onPanelResize,\n onPanelCollapse,\n updateSavedPanel,\n } = options;\n\n const preCollapseStates = new Map<string, PreCollapseState>();\n\n // ---- Size Conversion ----\n\n function convertToPixelSize(initialSize: ResizableSizeValue): number {\n return parseSizeToPixels(initialSize, containerSize.value);\n }\n\n // ============================================================================\n // CENTRALIZED COLLAPSE LOGIC\n // ============================================================================\n\n function processCollapseRequest(request: CollapseRequest): CollapseRequestResult {\n const { panelId, action, source } = request;\n const panel = panels.value.find(p => p.id === panelId);\n const isCollapse = action === 'collapse';\n\n const validationResult = validateCollapseRequest(panelId, panel, isCollapse);\n if (validationResult) return validationResult;\n\n if (isCollapse) {\n executeCollapse(panel!, source);\n } else {\n executeExpand(panel!);\n }\n\n onPanelCollapse(panelId, isCollapse);\n if (containerRef.value) {\n containerRef.value.dispatchEvent(new CustomEvent('panels-updated'));\n }\n\n const newState = isCollapse ? 'collapsed' : 'expanded';\n\n return { success: true, panelId, newState };\n }\n\n function validateCollapseRequest(\n panelId: string,\n panel: ResizablePanelState | undefined,\n isCollapse: boolean\n ): CollapseRequestResult | undefined {\n if (!panel) {\n return { success: false, reason: 'Panel not found', panelId, newState: 'unchanged' };\n }\n\n const currentlyCollapsed = panel.collapsed;\n if (isCollapse && currentlyCollapsed) {\n return { success: true, reason: 'Already collapsed', panelId, newState: 'unchanged' };\n }\n if (!isCollapse && !currentlyCollapsed) {\n return { success: true, reason: 'Already expanded', panelId, newState: 'unchanged' };\n }\n if (isCollapse && !panel.collapsible) {\n return { success: false, reason: 'Panel is not collapsible', panelId, newState: 'unchanged' };\n }\n\n return undefined;\n }\n\n function executeCollapse(panel: ResizablePanelState, source: CollapseRequestSource): void {\n const state: PreCollapseState = {\n sizes: new Map(),\n manualTargets: new Map(),\n containerSize: containerSize.value,\n };\n panels.value.forEach(p => {\n state.sizes.set(p.id, p.pixelSize);\n state.manualTargets.set(p.id, p.manualTargetSize);\n });\n preCollapseStates.set(panel.id, state);\n\n updateSavedPanel(panel.id, { collapsed: true, autoCollapsed: source === 'system' });\n\n // Clear manual ratios so remaining panels fill the freed space\n panels.value.forEach(p => {\n if (p.id !== panel.id && !p.collapsed) {\n updateSavedPanel(p.id, { manualTargetRatio: undefined });\n }\n });\n }\n\n function executeExpand(panel: ResizablePanelState): void {\n const wasAutoCollapsed = panel.autoCollapsed ?? false;\n\n const preCollapse = preCollapseStates.get(panel.id);\n\n if (preCollapse) {\n const viewportChangeRatio = Math.abs(containerSize.value - preCollapse.containerSize)\n / preCollapse.containerSize;\n const viewportChanged = viewportChangeRatio > 0.1;\n const shouldRestoreSizes = !viewportChanged || !wasAutoCollapsed;\n\n if (shouldRestoreSizes) {\n const savedPanelSize = preCollapse.sizes.get(panel.id);\n if (savedPanelSize !== undefined) {\n updateSavedPanel(panel.id, { pixelSize: savedPanelSize, collapsed: false, autoCollapsed: undefined });\n } else {\n updateSavedPanel(panel.id, { collapsed: false, autoCollapsed: undefined });\n }\n\n panels.value.forEach(p => {\n if (p.id === panel.id) return;\n const savedSize = preCollapse.sizes.get(p.id);\n const hadManualTargetBefore = preCollapse.manualTargets.get(p.id) !== undefined;\n const hasManualTargetNow = p.manualTargetSize !== undefined;\n\n if (!hadManualTargetBefore && !hasManualTargetNow && savedSize !== undefined) {\n updateSavedPanel(p.id, { pixelSize: savedSize });\n }\n });\n } else {\n updateSavedPanel(panel.id, { collapsed: false, autoCollapsed: undefined });\n }\n\n preCollapseStates.delete(panel.id);\n } else {\n const initialSize = parseSizeToPixels(panel.initialSize ?? DEFAULT_PANEL_SIZE, containerSize.value);\n const constrainedSize = applyPanelPixelConstraints(panel, initialSize, containerSize.value, 'system');\n updateSavedPanel(panel.id, { pixelSize: constrainedSize, collapsed: false, autoCollapsed: undefined });\n }\n }\n\n // ---- Panel Operations ----\n\n function commitPanelSize(panelId: string, pixels: number): void {\n const rounded = Math.round(pixels);\n const cSize = containerSize.value;\n const ratio = cSize > 0 ? rounded / cSize : undefined;\n updateSavedPanel(panelId, { pixelSize: rounded, manualTargetRatio: ratio });\n }\n\n function resizePanel(panelId: string, newPixelSize: number) {\n const panel = panels.value.find(p => p.id === panelId);\n if (!panel || panel.collapsed) return;\n\n const constrainedSize = applyPanelPixelConstraints(panel, newPixelSize, containerSize.value);\n commitPanelSize(panelId, constrainedSize);\n\n onPanelResize(panelId, constrainedSize);\n }\n\n /**\n */\n function collapsePanel(panelId: string, collapsed: boolean, options?: CollapseOptions) {\n const source: CollapseRequestSource = options?.isAutoCollapse ? 'system' : 'prop';\n\n processCollapseRequest({\n panelId,\n action: collapsed ? 'collapse' : 'expand',\n source,\n });\n }\n\n // ---- Panel Reset Operations ----\n\n function resetAdjacentPanels(beforePanel: ResizablePanelState, afterPanel: ResizablePanelState) {\n const combinedSpace = beforePanel.pixelSize + afterPanel.pixelSize;\n const beforeInitial = convertToPixelSize(beforePanel.initialSize || DEFAULT_PANEL_SIZE);\n const afterInitial = convertToPixelSize(afterPanel.initialSize || DEFAULT_PANEL_SIZE);\n const totalInitial = beforeInitial + afterInitial;\n\n const beforeSize = totalInitial > 0\n ? Math.round(combinedSpace * (beforeInitial / totalInitial))\n : Math.round(combinedSpace / 2);\n const afterSize = combinedSpace - beforeSize;\n\n updateSavedPanel(beforePanel.id, {\n pixelSize: beforeSize, manualTargetRatio: undefined,\n });\n updateSavedPanel(afterPanel.id, {\n pixelSize: afterSize, manualTargetRatio: undefined,\n });\n\n onPanelResize(beforePanel.id, beforeSize);\n onPanelResize(afterPanel.id, afterSize);\n }\n\n function resetAllPanelPairs() {\n for (let i = 0; i < panels.value.length - 1; i++) {\n const currentPanel = panels.value[i];\n const nextPanel = panels.value[i + 1];\n\n if (canResetPanelPair(currentPanel, nextPanel)) {\n resetAdjacentPanels(currentPanel, nextPanel);\n }\n }\n }\n\n function resetSpecificPanelPair(beforePanelId?: string, afterPanelId?: string) {\n const beforePanel = beforePanelId ? panels.value.find(p => p.id === beforePanelId) : undefined;\n const afterPanel = afterPanelId ? panels.value.find(p => p.id === afterPanelId) : undefined;\n\n if (beforePanel && afterPanel && canResetPanelPair(beforePanel, afterPanel)) {\n resetAdjacentPanels(beforePanel, afterPanel);\n }\n }\n\n function resetSinglePanel(panelId?: string) {\n if (!panelId) return;\n const panel = panels.value.find(p => p.id === panelId);\n if (!panel || panel.collapsed || panel.resizable === false) return;\n\n const initialSize = convertToPixelSize(panel.initialSize || DEFAULT_PANEL_SIZE);\n const delta = initialSize - panel.pixelSize;\n\n const panelIndex = panels.value.indexOf(panel);\n const adjacentPanel = panels.value.find((p, i) =>\n i !== panelIndex && !p.collapsed && p.resizable !== false\n );\n\n if (!adjacentPanel) return;\n\n const newAdjacentSize = adjacentPanel.pixelSize - delta;\n\n updateSavedPanel(panel.id, {\n pixelSize: initialSize, manualTargetRatio: undefined,\n });\n updateSavedPanel(adjacentPanel.id, { pixelSize: newAdjacentSize });\n\n onPanelResize(panel.id, initialSize);\n onPanelResize(adjacentPanel.id, newAdjacentSize);\n }\n\n function resetPanels(\n beforePanelId?: string,\n afterPanelId?: string,\n behavior: 'both' | 'before' | 'after' | 'all' = 'all'\n ) {\n try {\n if (behavior === 'all') {\n resetAllPanelPairs();\n } else if (behavior === 'before') {\n resetSinglePanel(beforePanelId);\n } else if (behavior === 'after') {\n resetSinglePanel(afterPanelId);\n } else {\n resetSpecificPanelPair(beforePanelId, afterPanelId);\n }\n } catch (error) {\n console.error('[resizable] Error in resetPanels:', error);\n }\n }\n\n // ---- Auto-Collapse/Expand ----\n\n function checkAutoCollapse(): string[] {\n const collapsedPanels: string[] = [];\n const currentContainerSize = containerSize.value;\n\n for (const panel of panels.value) {\n if (panel.collapsed || !panel.collapsible || !panel.collapseSizePixels) {\n continue;\n }\n\n if (currentContainerSize < panel.collapseSizePixels) {\n const result = processCollapseRequest({\n panelId: panel.id,\n action: 'collapse',\n source: 'system',\n });\n\n if (result.newState === 'collapsed') {\n collapsedPanels.push(panel.id);\n }\n }\n }\n\n return collapsedPanels;\n }\n\n function checkAutoExpand(): string[] {\n const expandedPanels: string[] = [];\n const currentContainerSize = containerSize.value;\n\n for (const panel of panels.value) {\n if (!panel.collapsed || !panel.autoCollapsed || !panel.collapseSizePixels) {\n continue;\n }\n\n if (currentContainerSize >= panel.collapseSizePixels) {\n const result = processCollapseRequest({\n panelId: panel.id,\n action: 'expand',\n source: 'system',\n });\n\n if (result.newState === 'expanded') {\n expandedPanels.push(panel.id);\n }\n }\n }\n\n return expandedPanels;\n }\n\n function processAutoCollapseExpand(): { collapsed: string[]; expanded: string[] } {\n const expanded = checkAutoExpand();\n const collapsed = checkAutoCollapse();\n\n return { collapsed, expanded };\n }\n\n return {\n commitPanelSize,\n resizePanel,\n collapsePanel,\n resetPanels,\n processCollapseRequest,\n checkAutoCollapse,\n checkAutoExpand,\n processAutoCollapseExpand,\n };\n}\n\n// ============================================================================\n// COLLAPSE RULE UTILITIES\n// ============================================================================\n\n/**\n * Sorts collapse rules by priority (lower numbers collapse first).\n * Creates a new sorted array - does not mutate the original.\n * Maintains stable sort for rules with equal priority.\n */\nexport function sortCollapseRules(rules: CollapseRule[]): CollapseRule[] {\n if (!rules || rules.length === 0) {\n return [];\n }\n\n const indexed = rules.map((rule, index) => ({ rule, index }));\n\n indexed.sort((a, b) => {\n const priorityDiff = a.rule.priority - b.rule.priority;\n if (priorityDiff !== 0) {\n return priorityDiff;\n }\n return a.index - b.index;\n });\n\n return indexed.map(item => item.rule);\n}\n\n// ============================================================================\n// AUTO-COLLAPSE UTILITIES\n// ============================================================================\n\nfunction getCollapseThreshold(\n panel: ResizablePanelState,\n rule: CollapseRule,\n containerSize: number\n): number | undefined {\n if (rule.minSizeBeforeCollapse !== undefined) {\n return parseSizeToPixels(rule.minSizeBeforeCollapse, containerSize);\n }\n return panel.userMinSizePixels;\n}\n\nfunction shouldPanelCollapse(\n panels: ResizablePanelState[],\n rule: CollapseRule,\n containerSize: number\n): string | undefined {\n const panel = panels.find(p => p.id === rule.panelId);\n\n if (!panel || panel.collapsed) {\n return undefined;\n }\n\n const threshold = getCollapseThreshold(panel, rule, containerSize);\n\n if (threshold === undefined) {\n return undefined;\n }\n\n return panel.pixelSize <= threshold ? panel.id : undefined;\n}\n\n/**\n * Checks which panels should auto-collapse based on their current size and collapse rules.\n * Returns panel IDs in priority order (lowest priority first = first to collapse).\n */\nexport function checkAutoCollapseRules(\n panels: ResizablePanelState[],\n collapseRules: CollapseRule[],\n containerSize: number\n): string[] {\n if (!panels || panels.length === 0 || !collapseRules || collapseRules.length === 0) {\n return [];\n }\n\n const sortedRules = sortCollapseRules(collapseRules);\n\n return sortedRules\n .map(rule => shouldPanelCollapse(panels, rule, containerSize))\n .filter((id): id is string => id !== undefined);\n}\n","/**\n * computeLayout — Pure Layout Engine\n *\n * Takes panel configs + container size and returns positions for every panel\n * and handle. Constraints are applied WITHIN the computation, not after.\n *\n * This is a pure function: no DOM access, no Vue reactivity, no localStorage,\n * no side effects. It takes data in and returns data out.\n *\n * Key design: proportional scaling\n * - Panels with manualTargetRatio scale to their stored ratio each render\n * - Panels without a ratio distribute remaining space proportionally\n * - Fixed panels (resizable: false) keep their exact pixel size\n * - Min/max constraints clamp results; overflow is redistributed in the same pass\n *\n * @see constraintResolver.ts\n */\n\nimport { DEFAULT_PANEL_SIZE, buildHandleId } from '../resizable_constants';\nimport type { ResizablePanelConfig } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\nimport { calculateConstraintHierarchy, clampToTier, type ConstraintHierarchy } from './constraintResolver';\n\n// ============================================================================\n// SAVED STATE TYPE (inlined from useResizableStorage — ported in Task #2)\n// ============================================================================\n\n/**\n * Data shape for a single panel's saved state in localStorage.\n * Defined here so computeLayout stays self-contained without depending\n * on the storage composable. useResizableStorage will re-export this\n * type when it is ported.\n */\nexport interface SavedPanelData {\n id: string;\n pixelSize: number;\n collapsed?: boolean;\n /** Whether this panel was auto-collapsed by the system (vs manually by user) */\n autoCollapsed?: boolean;\n /** Proportion of container this panel should occupy (set by drag, used for viewport scaling) */\n manualTargetRatio?: number;\n}\n\n// ============================================================================\n// INPUT / OUTPUT TYPES\n// ============================================================================\n\n/**\n * Input to the layout computation.\n * All values must be resolved before calling (no lazy-loading, no Vue refs).\n */\nexport interface LayoutInput {\n /** Registered panel configurations, in render order */\n panels: ResizablePanelConfig[];\n /** Current container width (row direction) or height (column direction), in pixels */\n containerSize: number;\n /**\n * Saved state from localStorage (optional).\n * When provided, sizes and collapsed state are restored from here.\n * IDs that do not match current panels are ignored.\n * Values that fail validation fall back to initialSize.\n */\n savedState?: SavedPanelData[];\n}\n\n/**\n * Computed position for a single panel.\n * All values are in pixels, relative to the container's top-left corner.\n */\nexport interface PanelPosition {\n id: string;\n /** Distance from the container's left edge to this panel's left edge */\n left: number;\n /** Distance from this panel's right edge to the container's right edge */\n right: number;\n /** Rendered width of the panel (0 when collapsed) */\n width: number;\n /** Whether the panel is currently collapsed */\n collapsed: boolean;\n /** Resolved constraints for this panel at the current container size */\n constraints: ConstraintHierarchy;\n}\n\n/**\n * Computed position for a single drag handle.\n * Handles sit between adjacent visible panels.\n */\nexport interface HandlePosition {\n /** Handle identifier: \"{beforePanelId}:{afterPanelId}\" */\n id: string;\n beforePanelId: string;\n afterPanelId: string;\n /** Pixel offset from the container's left edge to the handle's left edge */\n left: number;\n /**\n * True when the handle should be non-interactive.\n * Set when either adjacent panel is collapsed or resizable: false.\n */\n disabled: boolean;\n}\n\n/**\n * Output of computeLayout.\n * Immutable — create a new layout by calling computeLayout again.\n */\nexport interface LayoutResult {\n panels: Map<string, PanelPosition>;\n handles: HandlePosition[];\n}\n\n// ============================================================================\n// INTERNAL WORKING STATE\n// ============================================================================\n\n/**\n * Internal representation while computing sizes before positions are finalized.\n */\ninterface WorkingPanel {\n config: ResizablePanelConfig;\n constraints: ConstraintHierarchy;\n width: number;\n collapsed: boolean;\n /** True when resizable: false — panel keeps its exact pixel size, no handle rendered */\n isFixed: boolean;\n /**\n * The manual ratio stored from a previous drag (0–1, fraction of container).\n * When present, this panel's target width = manualTargetRatio * containerSize,\n * still subject to constraints.\n */\n manualTargetRatio?: number;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/**\n * Resolve initial pixel size for a panel from saved state or initialSize config.\n * Returns the raw size before constraint clamping.\n */\nfunction resolveRawSize(\n config: ResizablePanelConfig,\n containerSize: number,\n savedPanel: SavedPanelData | undefined\n): number {\n if (savedPanel !== undefined) {\n const saved = savedPanel.pixelSize;\n // Reject corrupted saved values\n if (!isFinite(saved) || saved < 0 || (containerSize > 0 && saved > containerSize * 2)) {\n return parseSizeToPixels(config.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n }\n return saved;\n }\n\n return parseSizeToPixels(config.initialSize ?? DEFAULT_PANEL_SIZE, containerSize);\n}\n\n/**\n * Determine whether a panel should be collapsed for a given input.\n * Priority: savedState.collapsed > config.collapsed\n */\nfunction resolveCollapsed(config: ResizablePanelConfig, savedPanel: SavedPanelData | undefined): boolean {\n if (savedPanel !== undefined && savedPanel.collapsed !== undefined) {\n return savedPanel.collapsed;\n }\n return Boolean(config.collapsed);\n}\n\n/**\n * Clamp a width to the constraint window.\n * Returns the clamped value and the amount of overflow/underflow.\n *\n * @param tier - Which constraints to apply:\n * 'user' — user-min/max (for ratio panels, user-dragged sizes)\n * 'system' — system-min/max falling back to user (for proportional panels,\n * viewport-driven redistribution)\n */\nfunction clampToConstraints(\n width: number,\n constraints: ConstraintHierarchy,\n tier: 'user' | 'system' = 'system'\n): { clamped: number; delta: number } {\n const clamped = clampToTier(width, constraints, tier);\n return { clamped, delta: clamped - width };\n}\n\n/**\n * Build the index of saved state for O(1) lookup during panel iteration.\n * Returns undefined if saved state is structurally incompatible with current panels.\n *\n * Incompatible = current panel IDs have entries NOT present in saved state.\n * (Panel IDs that exist in saved state but not current panels are simply ignored.)\n */\nfunction buildSavedIndex(\n savedState: SavedPanelData[] | undefined\n): Map<string, SavedPanelData> | undefined {\n if (!savedState) return undefined;\n return new Map<string, SavedPanelData>(savedState.map(s => [s.id, s]));\n}\n\n// ============================================================================\n// ALGORITHM\n// ============================================================================\n\n/**\n * Step 1: Build working panels with constraints and raw sizes.\n */\nfunction buildWorkingPanels(\n panels: ResizablePanelConfig[],\n containerSize: number,\n savedIndex: Map<string, SavedPanelData> | undefined\n): WorkingPanel[] {\n return panels.map(config => {\n const constraints = calculateConstraintHierarchy(config, containerSize);\n const savedPanel = savedIndex?.get(config.id);\n const collapsed = resolveCollapsed(config, savedPanel);\n const isFixed = config.resizable === false;\n\n const savedRatio = savedPanel?.manualTargetRatio;\n\n let rawWidth: number;\n if (collapsed) {\n rawWidth = 0;\n } else if (savedRatio !== undefined && containerSize > 0) {\n // Scale from ratio — the panel wants (ratio * container) pixels\n rawWidth = savedRatio * containerSize;\n } else {\n rawWidth = resolveRawSize(config, containerSize, savedPanel);\n }\n\n return {\n config,\n constraints,\n width: rawWidth,\n collapsed,\n isFixed,\n manualTargetRatio: savedRatio,\n };\n });\n}\n\n/**\n * Allocate space for Tier 1 (fixed) and Tier 2 (ratio) panels.\n * Mutates panel widths in place. Returns the total reserved space.\n */\nfunction allocateReservedPanels(visiblePanels: WorkingPanel[], containerSize: number): number {\n // Tier 1: Fixed panels (resizable: false)\n let reservedTotal = 0;\n for (const p of visiblePanels) {\n if (p.isFixed) {\n const { clamped } = clampToConstraints(p.width, p.constraints);\n p.width = clamped;\n reservedTotal += clamped;\n }\n }\n\n // Tier 2: Ratio panels (manualTargetRatio) — user constraints only.\n const ratioPanels = visiblePanels.filter(p => !p.isFixed && p.manualTargetRatio !== undefined);\n for (const p of ratioPanels) {\n const targetWidth = (p.manualTargetRatio ?? 0) * containerSize;\n const { clamped } = clampToConstraints(targetWidth, p.constraints, 'user');\n p.width = clamped;\n reservedTotal += clamped;\n }\n\n return reservedTotal;\n}\n\n/**\n * Iteratively clamp proportional panels to their constraint windows and\n * redistribute overflow/underflow to unclamped panels. Applies a final\n * clamp pass to catch floating-point drift.\n */\nfunction constrainAndRedistribute(propPanels: WorkingPanel[]): void {\n const maxPasses = propPanels.length + 1;\n\n for (let pass = 0; pass < maxPasses; pass++) {\n let totalDelta = 0;\n const clampedIds = new Set<string>();\n\n for (const p of propPanels) {\n const { clamped, delta } = clampToConstraints(p.width, p.constraints);\n if (delta !== 0) {\n p.width = clamped;\n clampedIds.add(p.config.id);\n totalDelta += delta;\n }\n }\n\n if (totalDelta === 0) break;\n\n const freePanels = propPanels.filter(p => !clampedIds.has(p.config.id));\n if (freePanels.length === 0) break;\n\n const changePerPanel = -totalDelta / freePanels.length;\n for (const p of freePanels) {\n p.width += changePerPanel;\n }\n }\n\n // Final clamp to catch any floating-point drift\n for (const p of propPanels) {\n const { clamped } = clampToConstraints(p.width, p.constraints);\n p.width = clamped;\n }\n}\n\n/**\n * If total allocated width < containerSize (all proportional panels hit max),\n * expand the last non-fixed visible panel to absorb the gap.\n */\nfunction applyFillGuarantee(visiblePanels: WorkingPanel[], propPanels: WorkingPanel[], containerSize: number): void {\n const allocatedTotal = visiblePanels.reduce((sum, p) => sum + p.width, 0);\n const gap = containerSize - allocatedTotal;\n if (gap > 1) {\n const lastFlexible = [...propPanels].reverse().find(p => !p.isFixed);\n if (lastFlexible) {\n lastFlexible.width += gap;\n }\n }\n}\n\n/**\n * Step 2: Distribute container space among non-collapsed panels.\n *\n * Distribution order (priority, highest first):\n * 1. Fixed panels (`resizable: false`) — keep exact initial pixel size\n * 2. Ratio panels (`manualTargetRatio`) — target (ratio × container), constrained\n * 3. Proportional panels — share remaining space using raw widths as weights\n *\n * After initial allocation, constraints are applied.\n * When a panel is min-clamped (forced larger), the extra space it consumed is\n * taken from unclamped proportional panels. When a panel is max-clamped (forced\n * smaller), the freed space is given back to unclamped proportional panels.\n * This redistribution iterates until stable (all panels within constraints) or\n * until no unclamped panels remain.\n */\nfunction distributeSpace(working: WorkingPanel[], containerSize: number): void {\n // Early exit for zero container\n if (containerSize <= 0) {\n working.forEach(p => {\n if (!p.collapsed) p.width = 0;\n });\n return;\n }\n\n const visiblePanels = working.filter(p => !p.collapsed);\n if (visiblePanels.length === 0) return;\n\n // ── Tier 1 + 2: Fixed and ratio panels ────────────────────────────────────\n const reservedTotal = allocateReservedPanels(visiblePanels, containerSize);\n\n // ── Tier 3: Proportional panels ───────────────────────────────────────────\n const propPanels = visiblePanels.filter(p => !p.isFixed && p.manualTargetRatio === undefined);\n const remainingSpace = Math.max(0, containerSize - reservedTotal);\n\n if (propPanels.length === 0) return;\n\n // Use current raw widths as proportional weights\n const totalPropWeight = propPanels.reduce((sum, p) => sum + Math.max(0, p.width), 0);\n\n // Initial allocation: proportional share of remaining space\n for (const p of propPanels) {\n if (totalPropWeight > 0) {\n p.width = (p.width / totalPropWeight) * remainingSpace;\n } else {\n // All weights are zero — distribute equally\n p.width = remainingSpace / propPanels.length;\n }\n }\n\n // ── Constraint pass with overflow redistribution ──────────────────────────\n constrainAndRedistribute(propPanels);\n\n // ── Fill guarantee ──────────────────────────────────────────────────────\n applyFillGuarantee(visiblePanels, propPanels, containerSize);\n}\n\n/**\n * Distribute +1px to panels with the largest fractional remainders,\n * skipping panels that are at their max constraint or fixed.\n */\nfunction distributeShortfall(remainders: { panel: WorkingPanel; remainder: number }[], shortfall: number): void {\n remainders.sort((a, b) => b.remainder - a.remainder);\n let remaining = shortfall;\n for (const { panel } of remainders) {\n if (remaining <= 0) break;\n const max = panel.constraints.systemMaxSizePixels ?? panel.constraints.userMaxSizePixels ?? Infinity;\n if (panel.width < max && !panel.isFixed) {\n panel.width += 1;\n remaining -= 1;\n }\n }\n}\n\n/**\n * Step 3: Round widths to integers and fix up rounding error.\n *\n * After distributing floating-point widths, some panels get ceil'd and some\n * floor'd. We use a \"largest remainder\" approach so the total always equals\n * the container size exactly (when not fully clamped by constraints).\n */\nfunction roundWidths(working: WorkingPanel[], containerSize: number): void {\n if (containerSize <= 0) return;\n\n const visiblePanels = working.filter(p => !p.collapsed);\n if (visiblePanels.length === 0) return;\n\n // Floor all widths first, collect remainders\n const remainders: { panel: WorkingPanel; remainder: number }[] = [];\n\n for (const p of visiblePanels) {\n const floored = Math.floor(p.width);\n remainders.push({ panel: p, remainder: p.width - floored });\n p.width = floored;\n }\n\n const currentTotal = visiblePanels.reduce((s, p) => s + p.width, 0);\n const shortfall = containerSize - currentTotal;\n\n distributeShortfall(remainders, shortfall);\n}\n\n/**\n * Step 4: Compute absolute left/right positions for each panel.\n */\nfunction computePositions(working: WorkingPanel[], containerSize: number): Map<string, PanelPosition> {\n const result = new Map<string, PanelPosition>();\n let cursor = 0;\n\n for (const p of working) {\n const width = p.collapsed ? 0 : p.width;\n const left = cursor;\n const right = Math.max(0, containerSize - left - width);\n\n result.set(p.config.id, {\n id: p.config.id,\n left,\n right,\n width,\n collapsed: p.collapsed,\n constraints: p.constraints,\n });\n\n cursor += width;\n }\n\n return result;\n}\n\n/**\n * Step 5: Compute handle positions.\n *\n * A handle is only generated for pairs of adjacent panels where BOTH panels\n * are resizable (resizable !== false). Pairs involving a fixed panel are\n * skipped entirely — no ResizableHandle component exists between them, and\n * including them in the array would shift the autoIndex values that handle\n * components use to look up their own position.\n *\n * Its left position equals the right edge of the before-panel.\n * It is disabled when either adjacent panel is collapsed.\n */\nfunction computeHandles(\n panels: ResizablePanelConfig[],\n positions: Map<string, PanelPosition>,\n): HandlePosition[] {\n const handles: HandlePosition[] = [];\n\n for (let i = 0; i < panels.length - 1; i++) {\n const before = panels[i];\n const after = panels[i + 1];\n\n // Skip pairs that involve a fixed (non-resizable) panel.\n // No ResizableHandle component is placed between fixed panels, so\n // generating an entry would misalign autoIndex → handles[] lookups.\n if (before.resizable === false || after.resizable === false) continue;\n\n const beforePos = positions.get(before.id);\n const afterPos = positions.get(after.id);\n\n if (!beforePos || !afterPos) continue;\n\n const disabled = beforePos.collapsed || afterPos.collapsed;\n\n handles.push({\n id: buildHandleId(before.id, after.id),\n beforePanelId: before.id,\n afterPanelId: after.id,\n left: beforePos.left + beforePos.width,\n disabled,\n });\n }\n\n return handles;\n}\n\n// ============================================================================\n// PUBLIC API\n// ============================================================================\n\n/**\n * Compute the complete layout for a group of resizable panels.\n *\n * This is a pure function — it has no side effects and does not read from\n * or write to the DOM, Vue reactivity, or localStorage.\n *\n * @param input - Panel configs, container size, and optional saved state\n * @returns Immutable layout result with panel positions and handle positions\n *\n * @example\n * const layout = computeLayout({\n * panels: registeredPanels,\n * containerSize: containerWidth,\n * savedState: loadFromStorage(),\n * });\n * const feedPos = layout.panels.get('feed-panel');\n * // feedPos.left, feedPos.width, feedPos.right, feedPos.collapsed\n */\nexport function computeLayout(input: LayoutInput): LayoutResult {\n const { panels, containerSize, savedState } = input;\n\n // Degenerate cases\n if (panels.length === 0) {\n return { panels: new Map(), handles: [] };\n }\n\n // Build saved-state lookup (returns undefined if incompatible with current panels)\n const savedIndex = buildSavedIndex(savedState);\n\n const working = buildWorkingPanels(panels, containerSize, savedIndex);\n distributeSpace(working, containerSize);\n roundWidths(working, containerSize);\n const positions = computePositions(working, containerSize);\n const handles = computeHandles(panels, positions);\n\n return { panels: positions, handles };\n}\n","import { DEFAULT_PANEL_SIZE } from '../resizable_constants';\nimport type { ResizablePanelConfig, ResizablePanelState } from '../resizable_constants';\nimport type { ResizableStorageAdapter, ResizableStoragePanelData } from '../resizable_constants';\nimport { parseSizeToPixels } from '../resizable_utils';\n\n// Re-export for backward compatibility\nexport type SavedPanelData = ResizableStoragePanelData;\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\nfunction validateRequiredProperties(data: Record<string, unknown>): boolean {\n return typeof data.id === 'string' && typeof data.pixelSize === 'number' && data.pixelSize >= 0;\n}\n\nfunction validateOptionalProperties(data: Record<string, unknown>): boolean {\n return (\n (data.collapsed === undefined || typeof data.collapsed === 'boolean') &&\n (data.autoCollapsed === undefined || typeof data.autoCollapsed === 'boolean')\n );\n}\n\nfunction isSavedPanelData(obj: unknown): obj is ResizableStoragePanelData {\n if (typeof obj !== 'object' || obj === null) return false;\n const data = obj as Record<string, unknown>;\n return validateRequiredProperties(data) && validateOptionalProperties(data);\n}\n\nfunction isSavedPanelDataArray(obj: unknown): obj is ResizableStoragePanelData[] {\n return Array.isArray(obj) && obj.every(item => isSavedPanelData(item));\n}\n\n/**\n * Validates a stored panel size against container bounds and returns a safe value.\n *\n * Checks for non-finite values, negative values, and oversized values (> 2x container).\n */\nexport function validateStoredPanelSize(\n storedSize: number,\n containerSize: number,\n panelConfig: ResizablePanelConfig\n): number {\n if (!isFinite(storedSize) || storedSize < 0) {\n return parseSizeToPixels(panelConfig.initialSize || DEFAULT_PANEL_SIZE, containerSize);\n }\n\n if (containerSize > 0 && storedSize > containerSize * 2) {\n console.warn(\n `[resizable] Stored size ${storedSize}px for panel '${panelConfig.id}' exceeds 2x container (${containerSize}px). Resetting.`\n );\n return parseSizeToPixels(panelConfig.initialSize || DEFAULT_PANEL_SIZE, containerSize);\n }\n\n return storedSize;\n}\n\n// ============================================================================\n// LOCALSTORAGE ADAPTER\n// ============================================================================\n\n/**\n * Create a localStorage-backed storage adapter.\n *\n * @param key - The localStorage key to use\n * @returns A ResizableStorageAdapter backed by localStorage\n *\n * @example\n * ```vue\n * <dt-resizable :storage=\"localStorageAdapter('my-layout')\">\n * ```\n */\nexport function localStorageAdapter(key: string): ResizableStorageAdapter {\n return {\n save(data: ResizableStoragePanelData[]): void {\n try {\n localStorage.setItem(key, JSON.stringify(data));\n } catch (error) {\n console.error('[resizable] Failed to save to localStorage:', error);\n }\n },\n\n load(): ResizableStoragePanelData[] | null {\n try {\n const saved = localStorage.getItem(key);\n if (!saved) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(saved);\n } catch {\n localStorage.removeItem(key);\n return null;\n }\n\n if (!isSavedPanelDataArray(parsed)) {\n localStorage.removeItem(key);\n return null;\n }\n\n return parsed;\n } catch (error) {\n console.warn('[resizable] Failed to load from localStorage:', error);\n try { localStorage.removeItem(key); } catch { /* ignore */ }\n return null;\n }\n },\n\n clear(): void {\n try {\n localStorage.removeItem(key);\n } catch { /* ignore */ }\n },\n };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\n/**\n * Composable for managing panel persistence.\n *\n * Accepts either a storageKey (string → auto-creates localStorage adapter)\n * or a custom ResizableStorageAdapter. The adapter takes precedence.\n *\n * @param storageKeyOrAdapter - localStorage key string, or null\n * @param customAdapter - Optional custom adapter (overrides storageKey)\n */\nexport function useResizableStorage(\n storageKeyOrAdapter: string | null,\n customAdapter?: ResizableStorageAdapter\n) {\n // Resolve the adapter: custom > storageKey > null\n const adapter: ResizableStorageAdapter | null = customAdapter\n ?? (storageKeyOrAdapter ? localStorageAdapter(storageKeyOrAdapter) : null);\n\n function saveToStorage(panels: ResizableStoragePanelData[] | ResizablePanelState[]): void {\n if (!adapter) return;\n\n const data: ResizableStoragePanelData[] = panels.map(panel => ({\n id: panel.id,\n pixelSize: panel.pixelSize,\n collapsed: panel.collapsed,\n autoCollapsed: panel.autoCollapsed,\n }));\n\n adapter.save(data);\n }\n\n function loadFromStorage(): ResizableStoragePanelData[] | null {\n if (!adapter) return null;\n\n const data = adapter.load();\n if (!data) return null;\n\n // Re-validate even if adapter returned data (defense in depth)\n if (!isSavedPanelDataArray(data)) {\n adapter.clear();\n return null;\n }\n\n return data;\n }\n\n function restorePanelFromStorage(panel: ResizablePanelState, savedPanel: ResizableStoragePanelData): void {\n if (panel.restoredFromStorage) return;\n\n if (savedPanel.pixelSize !== undefined) {\n panel.pixelSize = savedPanel.pixelSize;\n }\n if (savedPanel.collapsed !== undefined) {\n panel.collapsed = savedPanel.collapsed;\n }\n if (savedPanel.autoCollapsed !== undefined) {\n panel.autoCollapsed = savedPanel.autoCollapsed;\n }\n\n panel.restoredFromStorage = true;\n }\n\n function loadFromStorageWithValidation(panels: ResizablePanelState[]): boolean {\n const savedState = loadFromStorage();\n if (!savedState) return false;\n\n const currentPanelIds = new Set(panels.map(p => p.id));\n const savedPanelIds = new Set(savedState.map(p => p.id));\n\n // Clear if current panels don't all exist in saved (panel config changed)\n const hasIncompatiblePanels = Array.from(currentPanelIds).some(id => !savedPanelIds.has(id));\n if (hasIncompatiblePanels) {\n if (adapter) adapter.clear();\n return false;\n }\n\n savedState.forEach(savedPanel => {\n const panel = panels.find(p => p.id === savedPanel.id);\n if (panel) restorePanelFromStorage(panel, savedPanel);\n });\n\n return true;\n }\n\n function clearStorage(): void {\n if (adapter) adapter.clear();\n }\n\n return {\n saveToStorage,\n loadFromStorage,\n loadFromStorageWithValidation,\n restorePanelFromStorage,\n clearStorage,\n };\n}\n","/**\n * useResizableGroup — Reactive Layout Controller\n *\n * Replaces the timer-based initialization flow with a Vue `computed` that\n * re-runs synchronously whenever panels or the container size change.\n *\n * Responsibilities:\n * - Maintain the `registeredPanels` ref (panels call registerPanel/unregisterPanel)\n * - Track `containerSize` via a ResizeObserver (set up here, not in the component)\n * - Load saved state ONCE synchronously at creation time\n * - Expose `layout` computed that calls `computeLayout()`\n * - Expose `syncedPanels` computed that converts `LayoutResult` to `ResizablePanelState[]`\n *\n * @see computeLayout.ts — the pure layout engine\n */\n\nimport { ref, computed, watch, nextTick, type ComputedRef, type Ref } from 'vue';\nimport type { ResizablePanelConfig, ResizablePanelState, ResizableDirection } from '../resizable_constants';\nimport type { LayoutResult } from './computeLayout';\nimport type { SavedPanelData } from './useResizableStorage';\nimport { computeLayout } from './computeLayout';\nimport { useResizableStorage } from './useResizableStorage';\nimport { calculateConstraintHierarchy } from './constraintResolver';\nimport { validateContainerSize } from '../resizable_utils';\n\n// ============================================================================\n// OPTIONS\n// ============================================================================\n\nexport interface UseResizableGroupOptions {\n storageKey: string | null;\n direction: ComputedRef<ResizableDirection>;\n containerRef: Ref<HTMLElement | null>;\n /** Custom storage adapter. Overrides storageKey when provided. */\n storageAdapter?: import('../resizable_constants').ResizableStorageAdapter;\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\n\n/** Clamp a container dimension to a valid range. Delegates to the shared utility. */\nconst clampContainerSize = validateContainerSize;\n\n/**\n * Build a `ResizablePanelState` from a panel config + the layout result.\n * Reads `manualTargetRatio` and `autoCollapsed` from savedState.\n */\nfunction buildPanelState(\n config: ResizablePanelConfig,\n containerSize: number,\n layoutResult: LayoutResult,\n saved: SavedPanelData | undefined\n): ResizablePanelState {\n const position = layoutResult.panels.get(config.id);\n const constraints = position?.constraints ?? calculateConstraintHierarchy(config, containerSize);\n\n const pixelSize = position?.width ?? 0;\n const collapsed = position?.collapsed ?? Boolean(config.collapsed);\n\n return {\n ...config,\n pixelSize,\n collapsed,\n userMinSizePixels: constraints.userMinSizePixels,\n userMaxSizePixels: constraints.userMaxSizePixels,\n systemMinSizePixels: constraints.systemMinSizePixels,\n systemMaxSizePixels: constraints.systemMaxSizePixels,\n collapseSizePixels: constraints.collapseSizePixels,\n manualTargetRatio: saved?.manualTargetRatio,\n autoCollapsed: saved?.autoCollapsed,\n };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\nexport function useResizableGroup(options: UseResizableGroupOptions) {\n const { storageKey, direction, containerRef } = options;\n\n // ── Panel registry ──────────────────────────────────────────────────────────\n const registeredPanels = ref<ResizablePanelConfig[]>([]);\n\n // ── Container size ──────────────────────────────────────────────────────────\n const containerSize = ref(0);\n\n // ── Storage ─────────────────────────────────────────────────────────────────\n const storage = useResizableStorage(storageKey, options.storageAdapter);\n const savedState = ref<SavedPanelData[] | null>(storage.loadFromStorage());\n\n // ── isInitializing ─────────────────────────────────────────────────────────\n const isInitializing = ref(true);\n\n // ── Layout computed ─────────────────────────────────────────────────────────\n const layout = computed((): LayoutResult => {\n const panels = registeredPanels.value;\n const size = containerSize.value;\n\n if (panels.length === 0 || size <= 0) {\n return { panels: new Map(), handles: [] };\n }\n\n return computeLayout({\n panels,\n containerSize: size,\n savedState: savedState.value ?? undefined,\n });\n });\n\n // ── syncedPanels computed ───────────────────────────────────────────────────\n const syncedPanels = computed((): ResizablePanelState[] => {\n const result = layout.value;\n const size = containerSize.value;\n const savedMap = new Map(savedState.value?.map(s => [s.id, s]) ?? []);\n\n return registeredPanels.value.map(config => {\n const saved = savedMap.get(config.id);\n return buildPanelState(config, size, result, saved);\n });\n });\n\n // Flip isInitializing to false after first successful layout\n watch(\n layout,\n result => {\n if (result.panels.size > 0 && isInitializing.value) {\n isInitializing.value = false;\n }\n },\n { immediate: true }\n );\n\n // ── Panel index (O(1) lookup by id) ────────────────────────────────────────\n const panelMap = computed((): Map<string, ResizablePanelState> => {\n const map = new Map<string, ResizablePanelState>();\n for (const p of syncedPanels.value) map.set(p.id, p);\n return map;\n });\n\n // ── Panel registration ──────────────────────────────────────────────────────\n\n let sortScheduled = false;\n\n function registerPanel(config: ResizablePanelConfig): void {\n if (config.id.includes(':')) {\n console.warn(\n `[resizable] Panel id \"${config.id}\" contains ':' which is reserved as the handle separator. Use kebab-case.`\n );\n }\n\n const index = registeredPanels.value.findIndex(p => p.id === config.id);\n if (index !== -1) {\n registeredPanels.value = registeredPanels.value.map((p, i) => (i === index ? config : p));\n } else {\n registeredPanels.value = [...registeredPanels.value, config];\n\n if (!sortScheduled) {\n sortScheduled = true;\n nextTick(() => {\n registeredPanels.value = sortByDOMOrder(registeredPanels.value);\n sortScheduled = false;\n });\n }\n }\n }\n\n /**\n * Sort panel configs to match DOM order inside the container element.\n */\n function sortByDOMOrder(panels: ResizablePanelConfig[]): ResizablePanelConfig[] {\n const container = containerRef.value;\n if (!container) return panels;\n\n const panelElements = Array.from(container.querySelectorAll<HTMLElement>('.d-resizable-panel[data-panel-id]'));\n if (panelElements.length === 0) return panels;\n\n const domOrder = new Map<string, number>();\n panelElements.forEach((el, i) => {\n const id = el.getAttribute('data-panel-id');\n if (id) domOrder.set(id, i);\n });\n\n return [...panels].sort((a, b) => {\n const aPos = domOrder.get(a.id) ?? Infinity;\n const bPos = domOrder.get(b.id) ?? Infinity;\n return aPos - bPos;\n });\n }\n\n function unregisterPanel(id: string): void {\n registeredPanels.value = registeredPanels.value.filter(p => p.id !== id);\n }\n\n // ── Storage operations ──────────────────────────────────────────────────────\n\n function saveCurrentLayout(panels: ResizablePanelState[]): void {\n storage.saveToStorage(panels);\n savedState.value = panels.map(p => ({\n id: p.id,\n pixelSize: p.pixelSize,\n collapsed: p.collapsed,\n autoCollapsed: p.autoCollapsed,\n manualTargetRatio: p.manualTargetRatio,\n }));\n }\n\n function updateSavedPanel(panelId: string, updates: Partial<SavedPanelData>): void {\n if (!savedState.value) savedState.value = [];\n const idx = savedState.value.findIndex(s => s.id === panelId);\n if (idx >= 0) {\n savedState.value[idx] = { ...savedState.value[idx], ...updates };\n } else {\n // Use current computed size as default, not 0\n const currentPanel = syncedPanels.value.find(p => p.id === panelId);\n const currentSize = currentPanel?.pixelSize ?? 0;\n savedState.value.push({ id: panelId, pixelSize: currentSize, ...updates });\n }\n savedState.value = [...savedState.value]; // trigger reactivity\n\n // Persist to external storage\n storage.saveToStorage(savedState.value);\n }\n\n function reloadFromStorage(): void {\n savedState.value = storage.loadFromStorage();\n }\n\n function clearSavedState(): void {\n storage.clearStorage();\n savedState.value = null;\n }\n\n // ── ResizeObserver ─────────────────────────────────────────────────────────\n\n const resizeObserver = new ResizeObserver(entries => {\n for (const entry of entries) {\n const dim = direction.value === 'row' ? entry.contentRect.width : entry.contentRect.height;\n containerSize.value = clampContainerSize(Math.round(dim));\n }\n });\n\n function disconnectObserver(): void {\n resizeObserver.disconnect();\n }\n\n watch(\n containerRef,\n (el, prev) => {\n if (prev) resizeObserver.unobserve(prev);\n if (el) {\n const initial = direction.value === 'row' ? el.clientWidth : el.clientHeight;\n containerSize.value = clampContainerSize(initial);\n resizeObserver.observe(el);\n }\n },\n { immediate: true }\n );\n\n // ── Expose ─────────────────────────────────────────────────────────────────\n\n return {\n layout,\n syncedPanels,\n panelMap,\n containerSize,\n isInitializing,\n\n registerPanel,\n unregisterPanel,\n\n saveCurrentLayout,\n updateSavedPanel,\n reloadFromStorage,\n clearSavedState,\n\n disconnectObserver,\n };\n}\n","/**\n * useResizableDrag — Per-group drag state composable\n *\n * Each ResizableGroup instance gets its own drag composable, so nested groups can\n * drag independently without conflict.\n *\n * Key design: shadow state during drag.\n * - proposedBeforeSize / proposedAfterSize track the \"what-if\" layout during the drag.\n * - These are applied directly to DOM elements as inline styles (performance).\n * - The reactive layout state is NOT mutated during drag.\n * - On commit (mouseup / touchend): onDragEnd callback receives the final sizes.\n * - On cancel (Escape / unmount): inline styles are removed, DOM returns to layout state.\n */\n\nimport { reactive, onUnmounted, type ComputedRef, type Ref } from 'vue';\nimport type { ResizableDirection, ResizablePanelState } from '../resizable_constants';\nimport type { ResizeHandler } from './useResizableCalculations';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport type DragState = DragStateIdle | DragStateActive;\n\nexport interface DragStateIdle {\n isActive: false;\n handleId: null;\n beforePanelId: null;\n afterPanelId: null;\n proposedBeforeSize: 0;\n proposedAfterSize: 0;\n}\n\nexport interface DragStateActive {\n isActive: true;\n handleId: string;\n beforePanelId: string;\n afterPanelId: string;\n /** Proposed before-panel size during drag (shadow — not committed to layout yet) */\n proposedBeforeSize: number;\n /** Proposed after-panel size during drag (shadow — not committed to layout yet) */\n proposedAfterSize: number;\n}\n\n/** Initial idle state for reactive() initialization. */\nconst IDLE_STATE: DragStateIdle = {\n isActive: false,\n handleId: null,\n beforePanelId: null,\n afterPanelId: null,\n proposedBeforeSize: 0,\n proposedAfterSize: 0,\n};\n\nexport interface UseResizableDragOptions {\n direction: ComputedRef<ResizableDirection>;\n containerRef: Ref<HTMLElement | null>;\n panels: ComputedRef<ResizablePanelState[]> | Ref<ResizablePanelState[]>;\n containerSize: ComputedRef<number> | Ref<number>;\n resizeHandler: ResizeHandler;\n onDragEnd: (\n beforePanelId: string,\n afterPanelId: string,\n beforeSize: number,\n afterSize: number,\n sizesChanged: boolean\n ) => void;\n onDragStart?: (handleId: string) => void;\n}\n\n// ============================================================================\n// DOM HELPERS\n// ============================================================================\n\nfunction findPanelElement(container: HTMLElement, panelId: string): HTMLElement | null {\n return container.querySelector<HTMLElement>(`[data-panel-id=\"${panelId}\"]`);\n}\n\nfunction findHandleElement(container: HTMLElement, handleId: string): HTMLElement | null {\n return container.querySelector<HTMLElement>(`[data-handle-id=\"${handleId}\"]`);\n}\n\nfunction applyPanelDragStyle(element: HTMLElement, start: number, end: number): void {\n element.style.insetInlineStart = `${start}px`;\n element.style.insetInlineEnd = `${end}px`;\n element.style.inlineSize = '';\n}\n\nfunction clearDragStyle(element: HTMLElement): void {\n element.style.insetInlineStart = '';\n element.style.insetInlineEnd = '';\n element.style.inlineSize = '';\n}\n\nfunction applyHandleDragStyle(element: HTMLElement, position: number): void {\n element.style.insetInlineStart = `${Math.max(0, position)}px`;\n}\n\nfunction clearHandleDragStyle(element: HTMLElement): void {\n element.style.insetInlineStart = '';\n}\n\n// ============================================================================\n// PANEL LOOKUP\n// ============================================================================\n\n/**\n * Find the before/after panel pair for a given handle ID.\n * Handle IDs are formatted as \"{beforePanelId}:{afterPanelId}\".\n */\nexport function findPanelsForHandle(\n handleId: string,\n panels: ResizablePanelState[]\n): { beforePanel: ResizablePanelState | null; afterPanel: ResizablePanelState | null } {\n const sepIndex = handleId.indexOf(':');\n if (sepIndex === -1) return { beforePanel: null, afterPanel: null };\n\n const beforeId = handleId.slice(0, sepIndex);\n const afterId = handleId.slice(sepIndex + 1);\n\n const beforePanel = panels.find(p => p.id === beforeId) ?? null;\n const afterPanel = panels.find(p => p.id === afterId) ?? null;\n return { beforePanel, afterPanel };\n}\n\n// ============================================================================\n// COMPOSABLE\n// ============================================================================\n\n/**\n * Must be called from component setup context (uses `onUnmounted` lifecycle hook).\n */\nexport function useResizableDrag(options: UseResizableDragOptions) {\n const { direction, containerRef, panels, containerSize, resizeHandler, onDragEnd, onDragStart } = options;\n\n const dragState = reactive<DragState>({ ...IDLE_STATE });\n\n let beforePanelEl: HTMLElement | null = null;\n let afterPanelEl: HTMLElement | null = null;\n let handleEl: HTMLElement | null = null;\n\n let cachedBeforePanel: ResizablePanelState | null = null;\n let cachedAfterPanel: ResizablePanelState | null = null;\n\n let originalBeforeSize = 0;\n let originalAfterSize = 0;\n let beforePanelLeft = 0;\n let cachedContainerRect: DOMRect | null = null;\n\n let boundPointerMove: ((e: PointerEvent) => void) | null = null;\n let boundPointerUp: ((e: PointerEvent) => void) | null = null;\n\n function attachDocumentListeners(): void {\n boundPointerMove = (e: PointerEvent) => onDragMove(e);\n boundPointerUp = () => commitDrag();\n\n document.addEventListener('pointermove', boundPointerMove);\n document.addEventListener('pointerup', boundPointerUp);\n document.addEventListener('pointercancel', boundPointerUp);\n document.addEventListener('keydown', handleKeydown);\n }\n\n function removeDocumentListeners(): void {\n if (boundPointerMove) {\n document.removeEventListener('pointermove', boundPointerMove);\n boundPointerMove = null;\n }\n if (boundPointerUp) {\n document.removeEventListener('pointerup', boundPointerUp);\n document.removeEventListener('pointercancel', boundPointerUp);\n boundPointerUp = null;\n }\n document.removeEventListener('keydown', handleKeydown);\n }\n\n function cleanup(): void {\n removeDocumentListeners();\n\n document.body.style.userSelect = '';\n document.body.style.cursor = '';\n\n Object.assign(dragState, IDLE_STATE);\n\n beforePanelEl = null;\n afterPanelEl = null;\n handleEl = null;\n cachedBeforePanel = null;\n cachedAfterPanel = null;\n originalBeforeSize = 0;\n originalAfterSize = 0;\n beforePanelLeft = 0;\n cachedContainerRect = null;\n }\n\n function locateDragElements(\n container: HTMLElement,\n handleId: string,\n panelList: ResizablePanelState[]\n ): {\n beforePanel: ResizablePanelState;\n afterPanel: ResizablePanelState;\n beforeEl: HTMLElement;\n afterEl: HTMLElement;\n handleElement: HTMLElement | null;\n } | null {\n const { beforePanel, afterPanel } = findPanelsForHandle(handleId, panelList);\n if (!beforePanel || !afterPanel) {\n console.warn(`[resizable] No panel pair found for handle \"${handleId}\"`);\n return null;\n }\n\n const beforeEl = findPanelElement(container, beforePanel.id);\n const afterEl = findPanelElement(container, afterPanel.id);\n const handleElement = findHandleElement(container, handleId);\n\n if (!beforeEl || !afterEl) {\n console.warn(`[resizable] Panel element(s) not found for handle \"${handleId}\"`);\n return null;\n }\n\n return { beforePanel, afterPanel, beforeEl, afterEl, handleElement };\n }\n\n function startDrag(handleId: string): void {\n const container = containerRef.value;\n if (!container) return;\n\n const elements = locateDragElements(container, handleId, panels.value);\n if (!elements) return;\n\n beforePanelEl = elements.beforeEl;\n afterPanelEl = elements.afterEl;\n handleEl = elements.handleElement;\n\n cachedBeforePanel = elements.beforePanel;\n cachedAfterPanel = elements.afterPanel;\n\n originalBeforeSize = elements.beforePanel.pixelSize;\n originalAfterSize = elements.afterPanel.pixelSize;\n\n beforePanelLeft = parseFloat(beforePanelEl.style.insetInlineStart || '0');\n cachedContainerRect = container.getBoundingClientRect();\n\n Object.assign(dragState, {\n isActive: true,\n handleId,\n beforePanelId: elements.beforePanel.id,\n afterPanelId: elements.afterPanel.id,\n proposedBeforeSize: originalBeforeSize,\n proposedAfterSize: originalAfterSize,\n } satisfies DragStateActive);\n\n document.body.style.userSelect = 'none';\n document.body.style.cursor = direction.value === 'row' ? 'ew-resize' : 'ns-resize';\n\n attachDocumentListeners();\n onDragStart?.(handleId);\n }\n\n function computeDragPosition(\n event: PointerEvent,\n dir: ResizableDirection\n ): number {\n const rect = cachedContainerRect!;\n return dir === 'row' ? event.clientX - rect.left : event.clientY - rect.top;\n }\n\n function isDragMoveReady(): boolean {\n return (\n dragState.isActive &&\n !!containerRef.value &&\n !!beforePanelEl &&\n !!afterPanelEl &&\n !!dragState.handleId &&\n !!cachedBeforePanel &&\n !!cachedAfterPanel\n );\n }\n\n function onDragMove(event: PointerEvent): void {\n if (!isDragMoveReady()) return;\n\n const rawCursorPosition = computeDragPosition(event, direction.value);\n\n const result = resizeHandler.processResizeMove(\n rawCursorPosition,\n cachedBeforePanel!,\n cachedAfterPanel!,\n containerSize.value,\n dragState.handleId!,\n panels.value,\n beforePanelLeft\n );\n\n if (!result.isValidResize) return;\n\n if (dragState.proposedBeforeSize !== result.beforePanelSize) {\n dragState.proposedBeforeSize = result.beforePanelSize;\n }\n if (dragState.proposedAfterSize !== result.afterPanelSize) {\n dragState.proposedAfterSize = result.afterPanelSize;\n }\n\n const containerSizeValue = containerSize.value;\n const constrainedCursor = result.constrainedCursorPosition;\n const beforeRight = containerSizeValue - constrainedCursor;\n const handlePos = constrainedCursor - 2;\n\n const afterRight = containerSizeValue - constrainedCursor - result.afterPanelSize;\n\n applyPanelDragStyle(beforePanelEl!, beforePanelLeft, beforeRight);\n applyPanelDragStyle(afterPanelEl!, constrainedCursor, Math.max(0, afterRight));\n\n if (handleEl) {\n applyHandleDragStyle(handleEl, handlePos);\n }\n }\n\n function commitDrag(): void {\n if (!dragState.isActive) return;\n\n const beforePanelId = dragState.beforePanelId;\n const afterPanelId = dragState.afterPanelId;\n const beforeSize = dragState.proposedBeforeSize;\n const afterSize = dragState.proposedAfterSize;\n\n const capturedOriginalBeforeSize = originalBeforeSize;\n const capturedOriginalAfterSize = originalAfterSize;\n\n if (beforePanelEl) clearDragStyle(beforePanelEl);\n if (afterPanelEl) clearDragStyle(afterPanelEl);\n if (handleEl) clearHandleDragStyle(handleEl);\n\n cleanup();\n\n const sizesChanged = beforeSize !== capturedOriginalBeforeSize || afterSize !== capturedOriginalAfterSize;\n\n if (beforePanelId && afterPanelId) {\n onDragEnd(beforePanelId, afterPanelId, beforeSize, afterSize, sizesChanged);\n }\n }\n\n function cancelDrag(): void {\n if (!dragState.isActive) return;\n\n if (beforePanelEl && afterPanelEl) {\n clearDragStyle(beforePanelEl);\n clearDragStyle(afterPanelEl);\n }\n if (handleEl) {\n clearHandleDragStyle(handleEl);\n }\n\n cleanup();\n }\n\n function handleKeydown(event: KeyboardEvent): void {\n if (event.key === 'Escape' && dragState.isActive) {\n event.preventDefault();\n cancelDrag();\n }\n }\n\n onUnmounted(() => {\n cancelDrag();\n });\n\n return {\n dragState,\n startDrag,\n onDragMove,\n commitDrag,\n cancelDrag,\n cleanup,\n };\n}\n","import { onMounted, onUnmounted } from 'vue';\n\n// ─── Announcements (aria-live singleton with ref counting) ───────────────\n\nlet announcementElement: HTMLElement | null = null;\nlet announcementTimeout: ReturnType<typeof setTimeout> | undefined;\nlet announcementRefCount = 0;\n\nfunction getAnnouncementElement(): HTMLElement {\n if (!announcementElement) {\n announcementElement = document.getElementById('d-resizable-announcements');\n\n if (!announcementElement) {\n announcementElement = document.createElement('div');\n announcementElement.id = 'd-resizable-announcements';\n announcementElement.setAttribute('aria-live', 'polite');\n announcementElement.setAttribute('aria-atomic', 'true');\n announcementElement.style.position = 'absolute';\n announcementElement.style.left = '-10000px';\n announcementElement.style.width = '1px';\n announcementElement.style.height = '1px';\n announcementElement.style.overflow = 'hidden';\n document.body.appendChild(announcementElement);\n }\n }\n return announcementElement;\n}\n\nfunction announce(message: string): void {\n if (!message.trim()) return;\n\n if (announcementTimeout) {\n clearTimeout(announcementTimeout);\n }\n\n const element = getAnnouncementElement();\n element.textContent = '';\n\n announcementTimeout = setTimeout(() => {\n element.textContent = message;\n setTimeout(() => { element.textContent = ''; }, 1000);\n }, 100);\n}\n\n// ─── Composable ───────────────────────────────────────────────────────────\n\n/**\n * Manages a shared aria-live announcements region for all DtResizable\n * instances. Uses ref counting to create/destroy the singleton DOM element.\n */\nexport function useResizableAnnouncements() {\n onMounted(() => {\n announcementRefCount++;\n getAnnouncementElement();\n });\n\n onUnmounted(() => {\n if (announcementTimeout) {\n clearTimeout(announcementTimeout);\n }\n\n announcementRefCount--;\n if (announcementRefCount <= 0 && announcementElement) {\n announcementElement.remove();\n announcementElement = null;\n announcementRefCount = 0;\n }\n });\n\n return { announce };\n}\n","/**\n * Offset positioning composable for resize handles.\n *\n * Calculates dynamic offsets from DOM elements (e.g. a fixed header/toolbar)\n * so handles and panel content can avoid overlapping external UI.\n */\n\nimport {\n ref,\n computed,\n onMounted,\n type Ref,\n type ComputedRef,\n} from 'vue';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface ResizableOffsetOptions {\n /** CSS selector for the element to measure offset from (auto-measures block-size) */\n offsetElement?: string | null;\n /** Explicit pixel offset. Overrides offsetElement measurement when both provided. */\n offsetAmount?: number | null;\n /** Which edge(s) the offset applies to (default: 'start') */\n offsetDirection?: 'start' | 'end' | 'both';\n /** Layout direction — affects which dimension is measured */\n direction?: ComputedRef<'row' | 'column'> | Ref<'row' | 'column'>;\n}\n\nexport interface ResizableOffsetResult {\n calculatedOffset: Ref<number>;\n updateOffset: () => void;\n handleStyles: ComputedRef<Record<string, string>>;\n contentStyles: ComputedRef<Record<string, string>>;\n}\n\n// ─── Composable ───────────────────────────────────────────────────────────\n\nexport function useResizableOffset(\n options: ResizableOffsetOptions = {},\n): ResizableOffsetResult {\n const {\n offsetElement = null,\n offsetAmount = null,\n offsetDirection = 'start',\n direction = ref('row'),\n } = options;\n\n const calculatedOffset = ref(0);\n\n function updateOffset(): void {\n // Explicit amount wins over element measurement\n if (offsetAmount != null && offsetAmount > 0) {\n calculatedOffset.value = offsetAmount;\n return;\n }\n\n if (!offsetElement) { calculatedOffset.value = 0; return; }\n\n try {\n const element = document.querySelector(offsetElement);\n if (!element) { calculatedOffset.value = 0; return; }\n\n const rect = element.getBoundingClientRect();\n const dim = direction.value === 'row' ? rect.height : rect.width;\n calculatedOffset.value = dim;\n } catch (error) {\n console.warn('[resizable] Failed to measure offset element:', error);\n calculatedOffset.value = 0;\n }\n }\n\n // ── Computed styles — logical properties rotate with writing-mode ──\n\n const handleStyles = computed(() => {\n const styles: Record<string, string> = {};\n if (calculatedOffset.value <= 0) return styles;\n const px = `${calculatedOffset.value}px`;\n if (offsetDirection === 'start' || offsetDirection === 'both') styles.insetBlockStart = px;\n if (offsetDirection === 'end' || offsetDirection === 'both') styles.insetBlockEnd = px;\n return styles;\n });\n\n const contentStyles = computed(() => {\n const styles: Record<string, string> = {};\n if (calculatedOffset.value <= 0) return styles;\n const px = `${calculatedOffset.value}px`;\n if (offsetDirection === 'start' || offsetDirection === 'both') styles.paddingBlockStart = px;\n if (offsetDirection === 'end' || offsetDirection === 'both') styles.paddingBlockEnd = px;\n return styles;\n });\n\n onMounted(() => { updateOffset(); });\n\n return { calculatedOffset, updateOffset, handleStyles, contentStyles };\n}\n","<template>\n <div\n ref=\"containerRef\"\n :class=\"[\n 'd-resizable',\n `d-resizable--${currentDirection}`,\n { 'd-resizable--resizing': isResizing },\n props.class,\n ]\"\n :data-storage-key=\"props.storageKey || undefined\"\n >\n <!-- @slot Container for panels and handles. -->\n <slot\n :panels=\"group.syncedPanels.value\"\n :direction=\"currentDirection\"\n :is-resizing=\"isResizing\"\n :space-allocation-strategy=\"props.spaceAllocationStrategy\"\n :resize-panel=\"resizePanel\"\n :collapse-panel=\"collapsePanel\"\n :start-resize=\"startResize\"\n :stop-resize=\"stopResize\"\n />\n </div>\n</template>\n\n<script setup>\nimport {\n ref,\n computed,\n watch,\n onUnmounted,\n provide,\n} from 'vue';\nimport { RESIZABLE_CONTEXT_KEY, buildHandleId } from './resizable_constants';\nimport {\n useResizablePanelControls,\n useResizableGroup,\n useResizeHandling,\n checkAutoCollapseRules,\n useResizableAnnouncements,\n useResizableOffset,\n} from './composables';\nimport { useResizableDrag } from './composables/useResizableDrag';\n\nconst props = defineProps({\n /**\n * Layout direction. 'row' for horizontal, 'column' for vertical.\n * @values 'row', 'column'\n */\n direction: {\n type: String,\n default: 'row',\n },\n /** localStorage key for persisting panel sizes across page loads. */\n storageKey: {\n type: String,\n default: null,\n },\n /** Additional CSS classes applied to the container element. */\n class: {\n type: [String, Object, Array],\n default: '',\n },\n /**\n * Panel configurations array. When provided, panels are initialized\n * from this array instead of registering via child DtResizablePanel components.\n */\n panels: {\n type: Array,\n default: () => [],\n },\n /**\n * Strategy for redistributing space when panels open/close.\n * @values 'proportional', 'preserve-manual'\n */\n spaceAllocationStrategy: {\n type: String,\n default: 'proportional',\n validator: (val) => ['proportional', 'preserve-manual'].includes(val),\n },\n /** Rules defining which panels collapse first when space is constrained */\n collapseRules: {\n type: Array,\n default: () => [],\n },\n /** Custom storage adapter. Overrides storageKey when both are provided. */\n storage: {\n type: Object,\n default: null,\n },\n /** CSS selector for a fixed element to offset handles and panel content from. */\n offsetElement: { type: String, default: null },\n /** Explicit pixel offset. Overrides offsetElement measurement when both provided. */\n offsetAmount: { type: Number, default: null },\n /**\n * Which edge(s) the offset applies to.\n * @values 'start', 'end', 'both'\n */\n offsetDirection: { type: String, default: 'start' },\n /**\n * i18n message overrides for screen reader announcements.\n * Accepts keys from ResizableKeyboardMessages.\n */\n messages: {\n type: Object,\n default: () => ({}),\n },\n});\n\nconst emit = defineEmits(\n /**\n * @event panel-resize - Emitted when a panel is resized. Payload: (panelId, size).\n * @event panel-collapse - Emitted when a panel collapses or expands. Payload: (panelId, collapsed).\n * @event resize-start - Emitted when a resize drag begins. Payload: (handleId).\n * @event resize-end - Emitted when a resize drag ends. Payload: (handleId).\n */\n ['panel-resize', 'panel-collapse', 'resize-start', 'resize-end'],\n);\n\nconst containerRef = ref(null);\n\nconst currentDirection = computed(() => props.direction);\n\n// Note: storageKey and storage are captured at mount time. If they need to\n// change dynamically in the future, useResizableGroup should accept refs.\nconst group = useResizableGroup({\n storageKey: props.storageKey ?? null,\n direction: currentDirection,\n containerRef,\n storageAdapter: props.storage ?? undefined,\n});\n\nconst isResizing = ref(false);\nconst activeHandleId = ref(undefined);\n\nconst resizeHandler = useResizeHandling(() => group.containerSize.value);\n\nconst isInitializing = group.isInitializing;\nconst registerPanel = (config) => group.registerPanel(config);\nconst unregisterPanel = (id) => group.unregisterPanel(id);\nconst saveToStorage = (panels) => group.saveCurrentLayout(panels);\n\nconst {\n commitPanelSize,\n resizePanel,\n collapsePanel,\n resetPanels: originalResetPanels,\n processAutoCollapseExpand,\n} = useResizablePanelControls({\n panels: group.syncedPanels,\n containerSize: group.containerSize,\n containerRef,\n onPanelResize: (panelId, size) => emit('panel-resize', panelId, size),\n onPanelCollapse: (panelId, collapsed) => emit('panel-collapse', panelId, collapsed),\n updateSavedPanel: (panelId, updates) => group.updateSavedPanel(panelId, updates),\n});\n\nfunction resetPanels (beforePanelId, afterPanelId, behavior = 'all') {\n originalResetPanels(beforePanelId, afterPanelId, behavior);\n\n if (behavior === 'all') {\n group.syncedPanels.value.forEach(p => group.updateSavedPanel(p.id, { manualTargetRatio: undefined }));\n group.clearSavedState();\n } else {\n if (beforePanelId) group.updateSavedPanel(beforePanelId, { manualTargetRatio: undefined });\n if (afterPanelId) group.updateSavedPanel(afterPanelId, { manualTargetRatio: undefined });\n }\n}\n\nfunction processAutoCollapse () {\n processAutoCollapseExpand();\n if (!props.collapseRules?.length) return;\n const panels = group.syncedPanels.value;\n const panelsToCollapse = checkAutoCollapseRules(panels, props.collapseRules, group.containerSize.value);\n if (panelsToCollapse.length === 0) return;\n const panel = panels.find(p => p.id === panelsToCollapse[0]);\n if (panel && !panel.collapsed) collapsePanel(panelsToCollapse[0], true);\n}\n\nconst { announce } = useResizableAnnouncements();\n\nconst offset = useResizableOffset({\n offsetElement: props.offsetElement,\n offsetAmount: props.offsetAmount,\n offsetDirection: props.offsetDirection,\n direction: currentDirection,\n});\n\nconst handleInstances = new Set();\nfunction registerHandle (inst) { handleInstances.add(inst); }\nfunction unregisterHandle (inst) { handleInstances.delete(inst); }\n\nconst drag = useResizableDrag({\n direction: currentDirection,\n containerRef,\n panels: group.syncedPanels,\n containerSize: group.containerSize,\n resizeHandler,\n onDragStart (handleId) {\n isResizing.value = true;\n activeHandleId.value = handleId;\n emit('resize-start', handleId);\n },\n onDragEnd (beforePanelId, afterPanelId, beforeSize, afterSize, sizesChanged) {\n const handleId = drag.dragState.handleId ?? buildHandleId(beforePanelId, afterPanelId);\n isResizing.value = false;\n activeHandleId.value = undefined;\n\n if (sizesChanged) {\n commitPanelSize(beforePanelId, beforeSize);\n commitPanelSize(afterPanelId, afterSize);\n\n emit('resize-end', handleId);\n processAutoCollapse();\n }\n },\n});\n\nfunction startResize (handleId) { drag.startDrag(handleId); }\nfunction stopResize () { drag.cancelDrag(); }\nfunction savePanelsToStorage () { saveToStorage(group.syncedPanels.value); }\nfunction emitPanelResize (panelId, size) { emit('panel-resize', panelId, size); }\n\nwatch(group.syncedPanels, (panels) => {\n if (panels.length > 0 && !isInitializing.value) {\n processAutoCollapse();\n }\n}, { flush: 'post' });\n\nonUnmounted(() => {\n group.disconnectObserver();\n drag.cancelDrag();\n});\n\n// Provide single context object for child components\nprovide(RESIZABLE_CONTEXT_KEY, {\n layout: group.layout,\n panels: group.syncedPanels,\n panelMap: group.panelMap,\n direction: currentDirection,\n containerSize: group.containerSize,\n containerElement: computed(() => containerRef.value),\n isResizing: computed(() => isResizing.value),\n activeHandleId: computed(() => activeHandleId.value),\n isInitializing: computed(() => isInitializing.value),\n messages: props.messages,\n startResize: (handleId) => startResize(handleId),\n resetPanels,\n registerHandle,\n unregisterHandle,\n registerPanel,\n unregisterPanel,\n saveToStorage: savePanelsToStorage,\n announce,\n offsetHandleStyles: offset.handleStyles,\n offsetContentStyles: offset.contentStyles,\n collapsePanel,\n emitPanelResize,\n commitPanelSize,\n updateSavedPanel: (panelId, updates) => group.updateSavedPanel(panelId, updates),\n});\n\n// Expose methods for programmatic control\ndefineExpose({\n resizePanel,\n collapsePanel,\n resetPanels,\n state: computed(() => ({\n direction: currentDirection.value,\n panels: group.syncedPanels.value,\n containerSize: group.containerSize.value,\n isResizing: isResizing.value,\n activeHandleId: activeHandleId.value,\n })),\n panelConfigs: computed(() => props.panels),\n allocationStrategy: computed(() => props.spaceAllocationStrategy),\n});\n</script>\n"],"mappings":"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"}