Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/brand/src/3DContext/Div3D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ const extrudeDivSchema = {
scaleY: scaleTransformField('Scale Y'),
scaleZ: scaleTransformField('Scale Z'),
...Interactive.transformSchema,
...Interactive.borderSchema,
} as const satisfies InteractivitySchema;

const setRef = <ElementType,>(
Expand Down
1 change: 1 addition & 0 deletions packages/brand/src/Compose/WhatIsRemotion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const labelSchema = {
...Interactive.baseSchema,
...Interactive.transformSchema,
...Interactive.textSchema,
...Interactive.borderSchema,
children: {
type: 'text-content',
default: '',
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/HtmlInCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {addSequenceStackTraces} from './enable-sequence-stack-traces.js';
import type {InteractiveBaseProps} from './Interactive.js';
import {
baseSchema,
borderSchema,
transformSchema,
type InteractivitySchema,
} from './interactivity-schema.js';
Expand Down Expand Up @@ -784,6 +785,7 @@ export const htmlInCanvasSchema = {
hiddenFromList: false,
},
...transformSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

const HtmlInCanvasWrapped = withInteractivitySchema({
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/Img.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {getCrossOriginValue} from './get-cross-origin-value.js';
import type {InteractiveBaseProps} from './Interactive.js';
import {
baseSchema,
borderSchema,
transformSchema,
type InteractivitySchema,
} from './interactivity-schema.js';
Expand Down Expand Up @@ -387,6 +388,7 @@ export const imgSchema = {
},
...baseSchema,
...transformSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

const imgCanvasFallbackIncompatibleProps = new Set([
Expand Down
25 changes: 23 additions & 2 deletions packages/core/src/Interactive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
import {addSequenceStackTraces} from './enable-sequence-stack-traces.js';
import {
baseSchema,
borderSchema,
premountSchema,
sequenceSchema,
textContentSchema,
Expand Down Expand Up @@ -141,7 +142,18 @@ const interactiveElementSchema = {
...transformSchema,
} as const satisfies InteractivitySchema;

const interactiveBorderElementSchema = {
...interactiveElementSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

const interactiveTextElementSchema = {
...interactiveBorderElementSchema,
...textSchema,
...textContentSchema,
} as const satisfies InteractivitySchema;

const interactiveSvgTextElementSchema = {
...interactiveElementSchema,
...textSchema,
...textContentSchema,
Expand Down Expand Up @@ -266,6 +278,7 @@ export const Interactive = {
baseSchema,
transformSchema,
textSchema,
borderSchema,
premountSchema,
sequenceSchema,
withSchema,
Expand Down Expand Up @@ -302,8 +315,16 @@ export const Interactive = {
Small: makeInteractiveTextElement('small', '<Interactive.Small>'),
Span: makeInteractiveTextElement('span', '<Interactive.Span>'),
Strong: makeInteractiveTextElement('strong', '<Interactive.Strong>'),
Svg: makeInteractiveNonTextElement('svg', '<Interactive.Svg>'),
Text: makeInteractiveTextElement('text', '<Interactive.Text>'),
Svg: makeInteractiveElement(
'svg',
'<Interactive.Svg>',
interactiveBorderElementSchema,
),
Text: makeInteractiveElement(
'text',
'<Interactive.Text>',
interactiveSvgTextElementSchema,
),
Ul: makeInteractiveTextElement('ul', '<Interactive.Ul>'),
};

Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/animated-image/AnimatedImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import {addSequenceStackTraces} from '../enable-sequence-stack-traces.js';
import {
baseSchema,
borderSchema,
transformSchema,
type InteractivitySchema,
} from '../interactivity-schema.js';
Expand All @@ -38,7 +39,7 @@ import type {
import {serializeRequestInit} from './request-init';
import {resolveAnimatedImageSource} from './resolve-image-source';

const animatedImageSchema = {
export const animatedImageSchema = {
src: {
type: 'asset',
default: undefined,
Expand All @@ -57,6 +58,7 @@ const animatedImageSchema = {
keyframable: false,
},
...transformSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

const getCanvasPropsFromSequenceProps = (
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/canvas-image/CanvasImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {addSequenceStackTraces} from '../enable-sequence-stack-traces.js';
import {Freeze} from '../freeze.js';
import {
baseSchema,
borderSchema,
premountSchema,
premountStyleSchema,
transformSchema,
Expand Down Expand Up @@ -52,6 +53,7 @@ export const canvasImageSchema = {
},
},
...transformSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

type LoadedImage = {
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/effects/Solid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {addSequenceStackTraces} from '../enable-sequence-stack-traces.js';
import type {InteractiveBaseProps} from '../Interactive.js';
import {
baseSchema,
borderSchema,
transformSchema,
type InteractivitySchema,
} from '../interactivity-schema.js';
Expand Down Expand Up @@ -96,6 +97,7 @@ export const solidSchema = {
hiddenFromList: false,
},
...transformSchema,
...borderSchema,
} as const satisfies InteractivitySchema;

const SolidInner: React.FC<
Expand Down
35 changes: 35 additions & 0 deletions packages/core/src/interactivity-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,40 @@ export const textSchema = {
},
} as const satisfies InteractivitySchema;

export const borderSchema = {
'style.borderWidth': {
type: 'number',
default: undefined,
min: 0,
step: 1,
description: 'Border width',
hiddenFromList: false,
},
'style.borderStyle': {
type: 'enum',
// `none` is the CSS initial value of border-style.
default: 'none',
description: 'Border style',
variants: {
none: {},
hidden: {},
solid: {},
dashed: {},
dotted: {},
double: {},
groove: {},
ridge: {},
inset: {},
outset: {},
},
},
'style.borderColor': {
type: 'color',
default: undefined,
description: 'Border color',
},
} as const satisfies InteractivitySchema;

export const textContentSchema = {
children: {
type: 'text-content',
Expand Down Expand Up @@ -378,6 +412,7 @@ export const sequencePremountSchema = {

export const sequenceStyleSchema = {
...transformSchema,
...borderSchema,
...sequencePremountSchema,
} as const satisfies InteractivitySchema;

Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/test/find-props-to-delete.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ test('find right values to delete when upgrading a discriminated union', () => {
'style.scale',
'style.rotate',
'style.opacity',
'style.borderWidth',
'style.borderStyle',
'style.borderColor',
'premountFor',
'postmountFor',
'styleWhilePremounted',
Expand Down
59 changes: 59 additions & 0 deletions packages/core/src/test/with-interactivity-schema-helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {expect, test} from 'bun:test';
import {animatedImageSchema} from '../animated-image/AnimatedImage.js';
import {canvasImageSchema} from '../canvas-image/CanvasImage.js';
import type {SequenceControls} from '../CompositionManager.js';
import {solidSchema} from '../effects/Solid.js';
import {getComponentsToAddStacksTo} from '../enable-sequence-stack-traces.js';
Expand All @@ -7,9 +9,11 @@ import {
getFlatSchemaWithAllKeys,
} from '../flatten-schema.js';
import {htmlInCanvasSchema} from '../HtmlInCanvas.js';
import {imgSchema} from '../Img.js';
import {Interactive} from '../Interactive.js';
import {
baseSchema,
borderSchema,
extendSchemaWithSequenceName,
premountSchema,
sequencePremountSchema,
Expand All @@ -31,11 +35,27 @@ test('sequenceStyleSchema contains transform and premount fields', () => {
expect(Object.keys(sequenceStyleSchema).sort()).toEqual(
[
...Object.keys(transformSchema),
...Object.keys(borderSchema),
...Object.keys(sequencePremountSchema),
].sort(),
);
});

test('CSS box component schemas expose border controls', () => {
for (const schema of [
sequenceStyleSchema,
imgSchema,
animatedImageSchema,
canvasImageSchema,
htmlInCanvasSchema,
solidSchema,
]) {
expect('style.borderWidth' in schema).toBe(true);
expect('style.borderStyle' in schema).toBe(true);
expect('style.borderColor' in schema).toBe(true);
}
});

test('premount fields are not keyframable', () => {
expect(Object.keys(premountSchema).sort()).toEqual(
['postmountFor', 'premountFor'].sort(),
Expand Down Expand Up @@ -126,6 +146,9 @@ test('getFlatSchema(sequenceSchema) exposes every variant key', () => {
'style.rotate',
'style.transformOrigin',
'style.opacity',
'style.borderWidth',
'style.borderStyle',
'style.borderColor',
'premountFor',
'postmountFor',
'styleWhilePremounted',
Expand Down Expand Up @@ -300,6 +323,39 @@ test('textSchema exposes common text style fields', () => {
});
});

test('borderSchema exposes the longhand border style fields', () => {
expect(Object.keys(borderSchema).sort()).toEqual(
['style.borderColor', 'style.borderStyle', 'style.borderWidth'].sort(),
);
expect(borderSchema['style.borderWidth']).toMatchObject({
type: 'number',
default: undefined,
min: 0,
step: 1,
hiddenFromList: false,
});
expect(borderSchema['style.borderStyle']).toMatchObject({
type: 'enum',
default: 'none',
});
expect(Object.keys(borderSchema['style.borderStyle'].variants)).toEqual([
'none',
'hidden',
'solid',
'dashed',
'dotted',
'double',
'groove',
'ridge',
'inset',
'outset',
]);
expect(borderSchema['style.borderColor']).toMatchObject({
type: 'color',
default: undefined,
});
});

test('readValuesFromProps reads dot-notation keys via getNestedValue', () => {
const props = {
layout: 'absolute-fill',
Expand Down Expand Up @@ -364,6 +420,9 @@ test('selectActiveKeys exposes style.* keys when layout=absolute-fill', () => {
'style.rotate',
'style.transformOrigin',
'style.opacity',
'style.borderWidth',
'style.borderStyle',
'style.borderColor',
'premountFor',
'postmountFor',
].sort(),
Expand Down
10 changes: 10 additions & 0 deletions packages/docs/docs/interactive.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ Controls for text-related style props:

Use it for components that accept a `style` prop and render text.

### `Interactive.borderSchema`<AvailableFrom v="4.0.497" />

Controls for border-related style props:

`style.borderWidth`, `style.borderStyle` and `style.borderColor`.

The longhand properties are used rather than the `border` shorthand, because React does not expand shorthands. This lets each control read its own value, and allows `style.borderWidth` and `style.borderColor` to be animated.

Use it for components that accept a `style` prop and render a border.

### `Interactive.premountSchema`<AvailableFrom v="4.0.479" />

Controls for mounting behavior:
Expand Down
6 changes: 6 additions & 0 deletions packages/docs/docs/interactivity-schema.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ Text-related style props: `style.color`, `style.fontFamily`, `style.fontSize`, `

`style.fontFamily` is available from <AvailableFrom v="4.0.486" inline />.

### `Interactive.borderSchema`<AvailableFrom v="4.0.497" />

Border-related style props: `style.borderWidth`, `style.borderStyle` and `style.borderColor`.

The longhand properties are used rather than the `border` shorthand, because React does not expand shorthands. This lets each control read its own value, and allows `style.borderWidth` and `style.borderColor` to be animated.

### `Interactive.premountSchema`

Mounting props: `premountFor`, `postmountFor`, `styleWhilePremounted` and `styleWhilePostmounted`.
Expand Down
4 changes: 3 additions & 1 deletion packages/docs/elements/overlays/lower-third/lower-third.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const NameLowerThird: React.FC = () => {
fontFamily: 'Inter',
backgroundColor: 'rgba(255, 255, 255, 0.94)',
boxShadow: '0 6px 12px rgba(24, 24, 27, 0.2)',
border: '1px solid rgba(24, 24, 27, 0.08)',
borderWidth: 1,
borderStyle: 'solid',
borderColor: 'rgba(24, 24, 27, 0.08)',
opacity: interpolate(frame, [0, 18, 102, 119], [0, 1, 1, 0], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
Expand Down
3 changes: 2 additions & 1 deletion packages/gif/src/Gif.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type GifProps = InteractiveBaseProps &
* @description Displays a GIF that synchronizes with Remotions useCurrentFrame().
* @see [Documentation](https://remotion.dev/docs/gif)
*/
const gifSchema = {
export const gifSchema: InteractivitySchema = {
...Internals.baseSchema,
playbackRate: {
type: 'number',
Expand All @@ -39,6 +39,7 @@ const gifSchema = {
keyframable: false,
},
...Internals.transformSchema,
...Interactive.borderSchema,
} as const satisfies InteractivitySchema;

const GifInner = ({
Expand Down
Loading
Loading