Skip to content
Open
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
42 changes: 2 additions & 40 deletions src/input/styles.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SYSTEM } from '../internal/environment';
import customCssProps from '../internal/generated/custom-css-properties';
import { getInputStylesCss } from '../internal/utils/input-styles';
import { InputProps } from './interfaces';

export function getInputStyles(style: InputProps['style']) {
let properties = {};

if (SYSTEM === 'core') {
properties = {
borderRadius: style?.root?.borderRadius,
borderWidth: style?.root?.borderWidth,
fontSize: style?.root?.fontSize,
fontWeight: style?.root?.fontWeight,
paddingBlock: style?.root?.paddingBlock,
paddingInline: style?.root?.paddingInline,
[customCssProps.styleBackgroundDefault]: style?.root?.backgroundColor?.default,
[customCssProps.styleBackgroundDisabled]: style?.root?.backgroundColor?.disabled,
[customCssProps.styleBackgroundHover]: style?.root?.backgroundColor?.hover,
[customCssProps.styleBackgroundFocus]: style?.root?.backgroundColor?.focus,
[customCssProps.styleBackgroundReadonly]: style?.root?.backgroundColor?.readonly,
[customCssProps.styleBorderColorDefault]: style?.root?.borderColor?.default,
[customCssProps.styleBorderColorDisabled]: style?.root?.borderColor?.disabled,
[customCssProps.styleBorderColorHover]: style?.root?.borderColor?.hover,
[customCssProps.styleBorderColorFocus]: style?.root?.borderColor?.focus,
[customCssProps.styleBorderColorReadonly]: style?.root?.borderColor?.readonly,
[customCssProps.styleBoxShadowDefault]: style?.root?.boxShadow?.default,
[customCssProps.styleBoxShadowDisabled]: style?.root?.boxShadow?.disabled,
[customCssProps.styleBoxShadowHover]: style?.root?.boxShadow?.hover,
[customCssProps.styleBoxShadowFocus]: style?.root?.boxShadow?.focus,
[customCssProps.styleBoxShadowReadonly]: style?.root?.boxShadow?.readonly,
[customCssProps.styleColorDefault]: style?.root?.color?.default,
[customCssProps.styleColorDisabled]: style?.root?.color?.disabled,
[customCssProps.styleColorHover]: style?.root?.color?.hover,
[customCssProps.styleColorFocus]: style?.root?.color?.focus,
[customCssProps.styleColorReadonly]: style?.root?.color?.readonly,
[customCssProps.stylePlaceholderColor]: style?.placeholder?.color,
[customCssProps.stylePlaceholderFontSize]: style?.placeholder?.fontSize,
[customCssProps.stylePlaceholderFontWeight]: style?.placeholder?.fontWeight,
[customCssProps.stylePlaceholderFontStyle]: style?.placeholder?.fontStyle,
};

return properties;
}
return getInputStylesCss(style);
}
160 changes: 160 additions & 0 deletions src/internal/utils/__tests__/input-styles.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import customCssProps from '../../generated/custom-css-properties';
import { getInputStylesCss, InputStyleProps } from '../input-styles';

// Mock the environment module
jest.mock('../../environment', () => ({
SYSTEM: 'core',
}));

const fullStyle: InputStyleProps = {
root: {
borderRadius: '4px',
borderWidth: '1px',
fontSize: '14px',
fontWeight: '400',
paddingBlock: '8px',
paddingInline: '12px',
backgroundColor: {
default: '#ffffff',
disabled: '#f0f0f0',
hover: '#fafafa',
focus: '#ffffff',
readonly: '#f5f5f5',
},
borderColor: {
default: '#cccccc',
disabled: '#e0e0e0',
hover: '#999999',
focus: '#0073bb',
readonly: '#e0e0e0',
},
boxShadow: {
default: 'none',
disabled: 'none',
hover: '0 1px 2px rgba(0,0,0,0.1)',
focus: '0 0 0 2px #0073bb',
readonly: 'none',
},
color: {
default: '#000000',
disabled: '#999999',
hover: '#000000',
focus: '#000000',
readonly: '#666666',
},
},
placeholder: {
color: '#999999',
fontSize: '14px',
fontStyle: 'italic',
fontWeight: '400',
},
};

describe('getInputStylesCss', () => {
afterEach(() => {
jest.resetModules();
});

describe('when SYSTEM is core', () => {
test('returns full style object when all properties provided', () => {
const result = getInputStylesCss(fullStyle);

expect(result).toEqual({
borderRadius: '4px',
borderWidth: '1px',
fontSize: '14px',
fontWeight: '400',
paddingBlock: '8px',
paddingInline: '12px',
[customCssProps.styleBackgroundDefault]: '#ffffff',
[customCssProps.styleBackgroundDisabled]: '#f0f0f0',
[customCssProps.styleBackgroundHover]: '#fafafa',
[customCssProps.styleBackgroundFocus]: '#ffffff',
[customCssProps.styleBackgroundReadonly]: '#f5f5f5',
[customCssProps.styleBorderColorDefault]: '#cccccc',
[customCssProps.styleBorderColorDisabled]: '#e0e0e0',
[customCssProps.styleBorderColorHover]: '#999999',
[customCssProps.styleBorderColorFocus]: '#0073bb',
[customCssProps.styleBorderColorReadonly]: '#e0e0e0',
[customCssProps.styleBoxShadowDefault]: 'none',
[customCssProps.styleBoxShadowDisabled]: 'none',
[customCssProps.styleBoxShadowHover]: '0 1px 2px rgba(0,0,0,0.1)',
[customCssProps.styleBoxShadowFocus]: '0 0 0 2px #0073bb',
[customCssProps.styleBoxShadowReadonly]: 'none',
[customCssProps.styleColorDefault]: '#000000',
[customCssProps.styleColorDisabled]: '#999999',
[customCssProps.styleColorHover]: '#000000',
[customCssProps.styleColorFocus]: '#000000',
[customCssProps.styleColorReadonly]: '#666666',
[customCssProps.stylePlaceholderColor]: '#999999',
[customCssProps.stylePlaceholderFontSize]: '14px',
[customCssProps.stylePlaceholderFontWeight]: '400',
[customCssProps.stylePlaceholderFontStyle]: 'italic',
});
});

test('returns object with undefined values when style is undefined', () => {
const result = getInputStylesCss(undefined);

expect(result).toBeDefined();
expect(result?.borderRadius).toBeUndefined();
expect(result?.[customCssProps.styleBackgroundDefault]).toBeUndefined();
});

test('returns object with undefined values when style is empty object', () => {
const result = getInputStylesCss({});

expect(result).toBeDefined();
expect(result?.borderRadius).toBeUndefined();
});

describe('requireRoot parameter', () => {
test('returns undefined when requireRoot=true and style is undefined', () => {
const result = getInputStylesCss(undefined, true);
expect(result).toBeUndefined();
});

test('returns undefined when requireRoot=true and style.root is undefined', () => {
const result = getInputStylesCss({}, true);
expect(result).toBeUndefined();
});

test('returns undefined when requireRoot=true and style.root is missing', () => {
const result = getInputStylesCss({ placeholder: { color: '#999' } }, true);
expect(result).toBeUndefined();
});

test('returns style object when requireRoot=true and style.root is provided', () => {
const result = getInputStylesCss({ root: { borderRadius: '4px' } }, true);
expect(result).toBeDefined();
expect(result?.borderRadius).toBe('4px');
});
});
});

describe('when SYSTEM is not core', () => {
beforeEach(() => {
jest.resetModules();
jest.doMock('../../environment', () => ({
SYSTEM: 'visual-refresh',
}));
});

test('returns undefined regardless of style input', async () => {
const { getInputStylesCss: getInputStylesCssNonCore } = await import('../input-styles');

expect(getInputStylesCssNonCore(fullStyle)).toBeUndefined();
expect(getInputStylesCssNonCore(undefined)).toBeUndefined();
expect(getInputStylesCssNonCore({})).toBeUndefined();
});

test('returns undefined even with requireRoot=true', async () => {
const { getInputStylesCss: getInputStylesCssNonCore } = await import('../input-styles');

expect(getInputStylesCssNonCore(fullStyle, true)).toBeUndefined();
});
});
});
104 changes: 104 additions & 0 deletions src/internal/utils/input-styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SYSTEM } from '../environment';
import customCssProps from '../generated/custom-css-properties';

/**
* Shared style interface for input-like components (input, textarea, text-filter).
* Components can extend or alias this interface in their own interfaces.ts files.
*/
export interface InputStyleProps {
root?: {
backgroundColor?: {
default?: string;
disabled?: string;
focus?: string;
hover?: string;
readonly?: string;
};
borderColor?: {
default?: string;
disabled?: string;
focus?: string;
hover?: string;
readonly?: string;
};
borderRadius?: string;
borderWidth?: string;
boxShadow?: {
default?: string;
disabled?: string;
focus?: string;
hover?: string;
readonly?: string;
};
color?: {
default?: string;
disabled?: string;
focus?: string;
hover?: string;
readonly?: string;
};
fontSize?: string;
fontWeight?: string;
paddingBlock?: string;
paddingInline?: string;
};
placeholder?: {
color?: string;
fontSize?: string;
fontStyle?: string;
fontWeight?: string;
};
}

/**
* Maps input-like component style props to CSS custom properties.
* Used by input, textarea, and text-filter components.
*
* @param style - The style props to map
* @param requireRoot - If true, returns undefined when style.root is not provided (textarea behavior).
* If false, returns object with undefined values (input/text-filter behavior).
*/
export function getInputStylesCss(style: InputStyleProps | undefined, requireRoot = false) {
if (SYSTEM !== 'core') {
return undefined;
}

if (requireRoot && !style?.root) {
return undefined;
}

return {
borderRadius: style?.root?.borderRadius,
borderWidth: style?.root?.borderWidth,
fontSize: style?.root?.fontSize,
fontWeight: style?.root?.fontWeight,
paddingBlock: style?.root?.paddingBlock,
paddingInline: style?.root?.paddingInline,
[customCssProps.styleBackgroundDefault]: style?.root?.backgroundColor?.default,
[customCssProps.styleBackgroundDisabled]: style?.root?.backgroundColor?.disabled,
[customCssProps.styleBackgroundHover]: style?.root?.backgroundColor?.hover,
[customCssProps.styleBackgroundFocus]: style?.root?.backgroundColor?.focus,
[customCssProps.styleBackgroundReadonly]: style?.root?.backgroundColor?.readonly,
[customCssProps.styleBorderColorDefault]: style?.root?.borderColor?.default,
[customCssProps.styleBorderColorDisabled]: style?.root?.borderColor?.disabled,
[customCssProps.styleBorderColorHover]: style?.root?.borderColor?.hover,
[customCssProps.styleBorderColorFocus]: style?.root?.borderColor?.focus,
[customCssProps.styleBorderColorReadonly]: style?.root?.borderColor?.readonly,
[customCssProps.styleBoxShadowDefault]: style?.root?.boxShadow?.default,
[customCssProps.styleBoxShadowDisabled]: style?.root?.boxShadow?.disabled,
[customCssProps.styleBoxShadowHover]: style?.root?.boxShadow?.hover,
[customCssProps.styleBoxShadowFocus]: style?.root?.boxShadow?.focus,
[customCssProps.styleBoxShadowReadonly]: style?.root?.boxShadow?.readonly,
[customCssProps.styleColorDefault]: style?.root?.color?.default,
[customCssProps.styleColorDisabled]: style?.root?.color?.disabled,
[customCssProps.styleColorHover]: style?.root?.color?.hover,
[customCssProps.styleColorFocus]: style?.root?.color?.focus,
[customCssProps.styleColorReadonly]: style?.root?.color?.readonly,
[customCssProps.stylePlaceholderColor]: style?.placeholder?.color,
[customCssProps.stylePlaceholderFontSize]: style?.placeholder?.fontSize,
[customCssProps.stylePlaceholderFontWeight]: style?.placeholder?.fontWeight,
[customCssProps.stylePlaceholderFontStyle]: style?.placeholder?.fontStyle,
};
}
42 changes: 2 additions & 40 deletions src/text-filter/styles.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { SYSTEM } from '../internal/environment';
import customCssProps from '../internal/generated/custom-css-properties';
import { getInputStylesCss } from '../internal/utils/input-styles';
import { TextFilterProps } from './interfaces';

export function getTextFilterStyles(style: TextFilterProps['style']) {
let properties = {};

if (SYSTEM === 'core') {
properties = {
borderRadius: style?.root?.borderRadius,
borderWidth: style?.root?.borderWidth,
fontSize: style?.root?.fontSize,
fontWeight: style?.root?.fontWeight,
paddingBlock: style?.root?.paddingBlock,
paddingInline: style?.root?.paddingInline,
[customCssProps.styleBackgroundDefault]: style?.root?.backgroundColor?.default,
[customCssProps.styleBackgroundDisabled]: style?.root?.backgroundColor?.disabled,
[customCssProps.styleBackgroundHover]: style?.root?.backgroundColor?.hover,
[customCssProps.styleBackgroundFocus]: style?.root?.backgroundColor?.focus,
[customCssProps.styleBackgroundReadonly]: style?.root?.backgroundColor?.readonly,
[customCssProps.styleBorderColorDefault]: style?.root?.borderColor?.default,
[customCssProps.styleBorderColorDisabled]: style?.root?.borderColor?.disabled,
[customCssProps.styleBorderColorHover]: style?.root?.borderColor?.hover,
[customCssProps.styleBorderColorFocus]: style?.root?.borderColor?.focus,
[customCssProps.styleBorderColorReadonly]: style?.root?.borderColor?.readonly,
[customCssProps.styleBoxShadowDefault]: style?.root?.boxShadow?.default,
[customCssProps.styleBoxShadowDisabled]: style?.root?.boxShadow?.disabled,
[customCssProps.styleBoxShadowHover]: style?.root?.boxShadow?.hover,
[customCssProps.styleBoxShadowFocus]: style?.root?.boxShadow?.focus,
[customCssProps.styleBoxShadowReadonly]: style?.root?.boxShadow?.readonly,
[customCssProps.styleColorDefault]: style?.root?.color?.default,
[customCssProps.styleColorDisabled]: style?.root?.color?.disabled,
[customCssProps.styleColorHover]: style?.root?.color?.hover,
[customCssProps.styleColorFocus]: style?.root?.color?.focus,
[customCssProps.styleColorReadonly]: style?.root?.color?.readonly,
[customCssProps.stylePlaceholderColor]: style?.placeholder?.color,
[customCssProps.stylePlaceholderFontSize]: style?.placeholder?.fontSize,
[customCssProps.stylePlaceholderFontWeight]: style?.placeholder?.fontWeight,
[customCssProps.stylePlaceholderFontStyle]: style?.placeholder?.fontStyle,
};

return properties;
}
return getInputStylesCss(style);
}
Loading