From 934ba95580f415fcd713bbe0ede72642dbb255e9 Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Sat, 1 Mar 2025 15:29:38 +0100 Subject: [PATCH 1/2] feat: support percentage gap --- packages/layout/src/node/setGap.ts | 23 +----- packages/layout/src/node/setYogaValue.ts | 2 +- packages/layout/tests/node/setGap.test.ts | 87 +++++++++++++++++++++++ 3 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 packages/layout/tests/node/setGap.test.ts diff --git a/packages/layout/src/node/setGap.ts b/packages/layout/src/node/setGap.ts index 5028a54ed..c3a195b44 100644 --- a/packages/layout/src/node/setGap.ts +++ b/packages/layout/src/node/setGap.ts @@ -1,7 +1,6 @@ import * as Yoga from 'yoga-layout/load'; -import { isNil } from '@react-pdf/fns'; -import { SafeNode } from '../types'; +import setYogaValue from './setYogaValue'; /** * Set rowGap value to node's Yoga instance @@ -9,15 +8,7 @@ import { SafeNode } from '../types'; * @param value - Gap value * @returns Node instance wrapper */ -export const setRowGap = (value: number) => (node: SafeNode) => { - const { yogaNode } = node; - - if (!isNil(value) && yogaNode) { - yogaNode.setGap(Yoga.Gutter.Row, value); - } - - return node; -}; +export const setRowGap = setYogaValue('gap', Yoga.Gutter.Row); /** * Set columnGap value to node's Yoga instance @@ -25,12 +16,4 @@ export const setRowGap = (value: number) => (node: SafeNode) => { * @param value - Gap value * @returns Node instance wrapper */ -export const setColumnGap = (value: number) => (node: SafeNode) => { - const { yogaNode } = node; - - if (!isNil(value) && yogaNode) { - yogaNode.setGap(Yoga.Gutter.Column, value); - } - - return node; -}; +export const setColumnGap = setYogaValue('gap', Yoga.Gutter.Column); diff --git a/packages/layout/src/node/setYogaValue.ts b/packages/layout/src/node/setYogaValue.ts index 51e4c0529..3db301755 100644 --- a/packages/layout/src/node/setYogaValue.ts +++ b/packages/layout/src/node/setYogaValue.ts @@ -11,7 +11,7 @@ import { SafeNode } from '../types'; * @returns Node instance wrapper */ const setYogaValue = - (attr: string, edge?: Yoga.Edge) => + (attr: string, edge?: Yoga.Edge | Yoga.Gutter) => (value?: string | number | null) => (node: SafeNode) => { const { yogaNode } = node; diff --git a/packages/layout/tests/node/setGap.test.ts b/packages/layout/tests/node/setGap.test.ts new file mode 100644 index 000000000..3a6a629e6 --- /dev/null +++ b/packages/layout/tests/node/setGap.test.ts @@ -0,0 +1,87 @@ +import { beforeEach, describe, expect, test, vi } from 'vitest'; + +import * as Yoga from 'yoga-layout/load'; + +import { setRowGap, setColumnGap } from '../../src/node/setGap'; +import { SafeNode } from '../../src/types'; + +describe('node setGap', () => { + const mock = vi.fn(); + const mockPercent = vi.fn(); + + const node = { + type: 'VIEW', + props: {}, + style: {}, + children: [], + yogaNode: { + setGap: mock, + setGapPercent: mockPercent, + }, + } as SafeNode; + + const emptyNode = { + type: 'VIEW', + props: {}, + style: {}, + children: [], + box: { top: 0, right: 0, bottom: 0, left: 0, width: 10, height: 20 }, + } as SafeNode; + + beforeEach(() => { + mock.mockReset(); + mockPercent.mockReset(); + }); + + describe('setRowGap', () => { + test('should return node if no yoga node available', () => { + const result = setRowGap(null)(emptyNode); + + expect(result).toBe(emptyNode); + }); + + test('should call appropiate yoga node method for numeric values', () => { + const result = setRowGap(50)(node); + + expect(mock.mock.calls).toHaveLength(1); + expect(mock.mock.calls[0][0]).toBe(Yoga.Gutter.Row); + expect(mock.mock.calls[0][1]).toBe(50); + expect(result).toBe(node); + }); + + test('should call appropiate yoga node method for percent values', () => { + const result = setRowGap('50%')(node); + + expect(mockPercent.mock.calls).toHaveLength(1); + expect(mockPercent.mock.calls[0][0]).toBe(Yoga.Gutter.Row); + expect(mockPercent.mock.calls[0][1]).toBe(50); + expect(result).toBe(node); + }); + }); + + describe('setColumnGap', () => { + test('should return node if no yoga node available', () => { + const result = setColumnGap(null)(emptyNode); + + expect(result).toBe(emptyNode); + }); + + test('should call appropiate yoga node method for numeric values', () => { + const result = setColumnGap(50)(node); + + expect(mock.mock.calls).toHaveLength(1); + expect(mock.mock.calls[0][0]).toBe(Yoga.Gutter.Column); + expect(mock.mock.calls[0][1]).toBe(50); + expect(result).toBe(node); + }); + + test('should call appropiate yoga node method for percent values', () => { + const result = setColumnGap('50%')(node); + + expect(mockPercent.mock.calls).toHaveLength(1); + expect(mockPercent.mock.calls[0][0]).toBe(Yoga.Gutter.Column); + expect(mockPercent.mock.calls[0][1]).toBe(50); + expect(result).toBe(node); + }); + }); +}); From 52527508ace652374e712ec1d5d44a142367eec2 Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Sat, 1 Mar 2025 15:30:05 +0100 Subject: [PATCH 2/2] chore: add changeset --- .changeset/chilled-pumas-talk.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilled-pumas-talk.md diff --git a/.changeset/chilled-pumas-talk.md b/.changeset/chilled-pumas-talk.md new file mode 100644 index 000000000..b571130f1 --- /dev/null +++ b/.changeset/chilled-pumas-talk.md @@ -0,0 +1,5 @@ +--- +"@react-pdf/layout": minor +--- + +feat: support percentage gap