Skip to content

Add makeResponsiveValue for readable value. #2120

@PeterlitsZo

Description

@PeterlitsZo

I know that we can use array to get the responsive value. But sometime I hope there is a function that put a object with readable key and output the array.

Here is my solution:

expect(mRV({_: '30%', md: '40%'})).toBe(['30%', null, '40%', null, null]);
const __breakpointNameWithoutInitArray = ['sm', 'md', 'lg', 'xl'] as const;
if ('_' in __breakpointNameWithoutInitArray) {
  throw new Error(
    `Be sure that '_' cannot in the \`__breakpointNameWithoutInitArray\``,
  );
}

export type BreakpointNameWithoutInit =
  typeof __breakpointNameWithoutInitArray[number];
export type BreakpointName = BreakpointNameWithoutInit | '_';
export type BreakpointMapWithoutInit = {
  [size in BreakpointNameWithoutInit]: number;
};
export type BreakpointMap = {
  [size in BreakpointName]: number;
};

// Make breakpoints array and its name map(to breakpoints array's index).
// e.g. makeBreakPoints([['640px', 'sm'], ['780px', 'md']]) === [['640px',
// '780px'], {'sm': 0, 'md': 1}].
const makeBreakPoints = (
  breakpointsAndNames: Array<[string, BreakpointNameWithoutInit]>,
): [Array<string>, BreakpointMapWithoutInit] => {
  if (breakpointsAndNames.length !== __breakpointNameWithoutInitArray.length) {
    throw new Error(
      `Be sure that those names ${__breakpointNameWithoutInitArray},` +
        "are all in the argument `breakpointsAndNames`'s breakpoints' names",
    );
  }

  let result: [Array<string>, { [size: string]: number }] = [[], {}];
  let breakpointNames = new Set();
  for (let i = 0; i < breakpointsAndNames.length; i++) {
    let [size, name] = breakpointsAndNames[i];

    // make sure breakpoint name is unique.
    if (name in breakpointNames) {
      throw new Error("Be sure that breakpoint's name is unique.");
    }
    breakpointNames.add(name);

    result[0].push(size);
    result[1][name] = i;
  }
  return [result[0], result[1] as BreakpointMapWithoutInit];
};

const [breakpoints, breakpointNames] = makeBreakPoints([
  ['640px', 'sm'], // breakpoint 0
  ['780px', 'md'], // breakpoint 1
  ['1024px', 'lg'], // breakpoint 2
  ['1536px', 'xl'], // breakpoint 3
]);

// Make responsive value. (alias: mRV).
// e.g. If breakpointNames(should use `makeBreakPoints` to make) is {'sm': 0,
// 'md': 1, 'lg': 2, 'xl': 3}, then mRV<string>({_: '10px', 'md': '20px'}) ===
// ['10px', null, '20px', null, null].
export const makeResponsiveValue = <T>(
  argument: Partial<{ [size in BreakpointName]: T }>,
): (T | null)[] => {
  let result: (T | null)[] = fill(Array(breakpoints.length + 1), null);
  for (const s in argument) {
    const size = s as BreakpointName;
    const value = argument[size];
    if (isUndefined(value)) continue;
    if (size === '_') {
      result[0] = value;
      continue;
    }
    result[breakpointNames[size] + 1] = value;
  }
  return result;
};

export const mRV = makeResponsiveValue;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions