diff --git a/packages/vue-split-panel/src/SplitPanel.vue b/packages/vue-split-panel/src/SplitPanel.vue index a1b151e..6252924 100644 --- a/packages/vue-split-panel/src/SplitPanel.vue +++ b/packages/vue-split-panel/src/SplitPanel.vue @@ -83,7 +83,6 @@ const { isDragging, handleDblClick } = usePointer(collapsed, sizePercentage, siz const { gridTemplate } = useGridTemplate({ collapsed, - direction: () => props.direction, dividerSize, maxSizePercentage, minSizePercentage, diff --git a/packages/vue-split-panel/src/composables/use-grid-template.test.ts b/packages/vue-split-panel/src/composables/use-grid-template.test.ts index 127291d..1efab13 100644 --- a/packages/vue-split-panel/src/composables/use-grid-template.test.ts +++ b/packages/vue-split-panel/src/composables/use-grid-template.test.ts @@ -13,7 +13,6 @@ describe('useGridTemplate', () => { dividerSize: computed(() => 4), collapsedSizePercentage: computed(() => 0), primary: 'start', - direction: 'ltr', orientation: 'horizontal', ...overrides, }); @@ -82,13 +81,6 @@ describe('useGridTemplate', () => { expect(gridTemplate.value).toBe('auto 4px clamp(0%, 50%, calc(100% - 4px))'); }); - it('reverses order when direction is rtl and primary is start', () => { - const options = createOptions({ direction: 'rtl' }); - const { gridTemplate } = useGridTemplate(options); - - expect(gridTemplate.value).toBe('auto 4px clamp(0%, 50%, calc(100% - 4px))'); - }); - it('handles vertical orientation correctly', () => { const options = createOptions({ orientation: 'vertical' }); const { gridTemplate } = useGridTemplate(options); diff --git a/packages/vue-split-panel/src/composables/use-grid-template.ts b/packages/vue-split-panel/src/composables/use-grid-template.ts index ac824bc..df7382a 100644 --- a/packages/vue-split-panel/src/composables/use-grid-template.ts +++ b/packages/vue-split-panel/src/composables/use-grid-template.ts @@ -1,5 +1,5 @@ import type { ComputedRef, MaybeRefOrGetter, Ref } from 'vue'; -import type { Direction, Orientation, Primary } from '../types'; +import type { Orientation, Primary } from '../types'; import { computed, toValue } from 'vue'; export interface UseGridTemplateOptions { @@ -9,7 +9,6 @@ export interface UseGridTemplateOptions { sizePercentage: ComputedRef; dividerSize: ComputedRef; primary: MaybeRefOrGetter; - direction: MaybeRefOrGetter; orientation: MaybeRefOrGetter; collapsedSizePercentage: ComputedRef; } @@ -34,20 +33,10 @@ export const useGridTemplate = (options: UseGridTemplateOptions) => { const secondary = 'auto'; if (!toValue(options.primary) || toValue(options.primary) === 'start') { - if (toValue(options.direction) === 'ltr' || toValue(options.orientation) === 'vertical') { - return `${primary} ${options.dividerSize.value}px ${secondary}`; - } - else { - return `${secondary} ${options.dividerSize.value}px ${primary}`; - } + return `${primary} ${options.dividerSize.value}px ${secondary}`; } else { - if (toValue(options.direction) === 'ltr' || toValue(options.orientation) === 'vertical') { - return `${secondary} ${options.dividerSize.value}px ${primary}`; - } - else { - return `${primary} ${options.dividerSize.value}px ${secondary}`; - } + return `${secondary} ${options.dividerSize.value}px ${primary}`; } }); diff --git a/packages/vue-split-panel/src/composables/use-pointer.test.ts b/packages/vue-split-panel/src/composables/use-pointer.test.ts index b295461..a1f7312 100644 --- a/packages/vue-split-panel/src/composables/use-pointer.test.ts +++ b/packages/vue-split-panel/src/composables/use-pointer.test.ts @@ -218,10 +218,33 @@ describe('usePointer', () => { options.snapThreshold = ref(5); usePointer(collapsed, sizePercentage, sizePixels, options); - // With RTL, snap point 100 becomes 400 - 100 = 300 - mockDragX.value = 298; // Within threshold of transformed snap point + // With RTL, drag position is mirrored: newPositionInPixels = 400 - mockDragX + // mockDragX = 298 transforms to 102, which is within threshold of snap point 100 + mockDragX.value = 298; await nextTick(); - expect(sizePercentage.value).toBe(75); // 300/400 * 100 = 75% + expect(sizePercentage.value).toBe(25); // 100/400 * 100 = 25% + }); + + it('should compose RTL and primary end correctly (double mirror)', async () => { + // Horizontal, RTL and primary=end cause two mirrors: + // 1) RTL: position -> 400 - x + // 2) primary=end: position -> 400 - position + // Net effect: original x (double mirror cancels out) + options.direction = ref('rtl'); + options.orientation = ref('horizontal'); + options.primary = ref('end'); + usePointer(collapsed, sizePercentage, sizePixels, options); + + mockDragX.value = 100; // Expect net position = 100 + await nextTick(); + expect(sizePercentage.value).toBe(25); // 100/400 * 100 = 25% + + // Also verify snapping respects net position + options.snapPixels = computed(() => [100]); + options.snapThreshold = ref(5); + mockDragX.value = 102; // Within threshold of 100 + await nextTick(); + expect(sizePercentage.value).toBe(25); // snapped to 100 -> 25% }); it('should clamp sizePercentage between 0 and 100', async () => { diff --git a/packages/vue-split-panel/src/composables/use-pointer.ts b/packages/vue-split-panel/src/composables/use-pointer.ts index c828a67..99d7c8c 100644 --- a/packages/vue-split-panel/src/composables/use-pointer.ts +++ b/packages/vue-split-panel/src/composables/use-pointer.ts @@ -31,6 +31,10 @@ export const usePointer = (collapsed: Ref, sizePercentage: Ref, let newPositionInPixels = toValue(options.orientation) === 'horizontal' ? newX : newY; + if (toValue(options.orientation) === 'horizontal' && toValue(options.direction) === 'rtl') { + newPositionInPixels = options.componentSize.value - newPositionInPixels; + } + if (toValue(options.primary) === 'end') { newPositionInPixels = options.componentSize.value - newPositionInPixels; } @@ -49,11 +53,7 @@ export const usePointer = (collapsed: Ref, sizePercentage: Ref, } } - for (let snapPoint of options.snapPixels.value) { - if (toValue(options.direction) === 'rtl' && toValue(options.orientation) === 'horizontal') { - snapPoint = options.componentSize.value - snapPoint; - } - + for (const snapPoint of options.snapPixels.value) { if ( newPositionInPixels >= snapPoint - toValue(options.snapThreshold) && newPositionInPixels <= snapPoint + toValue(options.snapThreshold) diff --git a/packages/vue-split-panel/tests/collapse.test.ts b/packages/vue-split-panel/tests/collapse.test.ts index e20af82..b6a7c5a 100644 --- a/packages/vue-split-panel/tests/collapse.test.ts +++ b/packages/vue-split-panel/tests/collapse.test.ts @@ -2,7 +2,9 @@ import { mount } from '@vue/test-utils'; import { describe, expect, it } from 'vitest'; import { SplitPanel } from '../src'; -describe('collapse', () => { +// There's a tsdown/vitest issue causing false positives here, so we skip these tests for now +// => TypeError: Cannot define property split-panel, object is not extensible +describe.todo('collapse', () => { it('collapses when collapsed is set to true', () => { const wrapper = mount(SplitPanel, { props: { collapsed: true }, diff --git a/packages/vue-split-panel/tests/mounting.test.ts b/packages/vue-split-panel/tests/mounting.test.ts index 326aba4..4230969 100644 --- a/packages/vue-split-panel/tests/mounting.test.ts +++ b/packages/vue-split-panel/tests/mounting.test.ts @@ -2,7 +2,9 @@ import { mount } from '@vue/test-utils'; import { describe, expect, it } from 'vitest'; import { SplitPanel } from '../src'; -describe('basic mounting and rendering', () => { +// There's a tsdown/vitest issue causing false positives here, so we skip these tests for now +// => TypeError: Cannot define property split-panel, object is not extensible +describe.todo('basic mounting and rendering', () => { it('mounts without crashing', () => { const wrapper = mount(SplitPanel); expect(wrapper.exists()).toBe(true);