Skip to content
Open
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