Skip to content

Commit

Permalink
Merge pull request #6 from timelessco/refactor/accordion-slider
Browse files Browse the repository at this point in the history
refactor(accordion): ♻️  restructure source code
  • Loading branch information
navin-moorthy authored Aug 25, 2020
2 parents fd1817b + 1d742d6 commit 48c10fc
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 421 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist
coverage
package.json
package-lock.json
yarn.lock
yarn.lock
storybook-static
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,28 @@
"storybook": "start-storybook -p 6006"
},
"dependencies": {
"@chakra-ui/hooks": "1.0.0-next.7",
"@chakra-ui/utils": "1.0.0-next.7",
"@chakra-ui/hooks": "1.0.0-rc.2",
"@chakra-ui/utils": "1.0.0-rc.2",
"@types/lodash.debounce": "^4.0.6",
"lodash.debounce": "^4.0.8",
"reakit": "^1.2.2",
"reakit-system": "^0.14.2",
"reakit-utils": "^0.14.2"
"reakit": "^1.2.3",
"reakit-system": "^0.14.3",
"reakit-utils": "^0.14.3"
},
"devDependencies": {
"@babel/core": "7.11.1",
"@babel/core": "7.11.4",
"@commitlint/cli": "9.1.2",
"@commitlint/config-conventional": "9.1.2",
"@storybook/addon-a11y": "6.0.14",
"@storybook/addon-actions": "6.0.14",
"@storybook/addon-essentials": "6.0.14",
"@storybook/addon-links": "6.0.14",
"@storybook/addon-storysource": "6.0.14",
"@storybook/react": "6.0.14",
"@types/react": "16.9.46",
"@storybook/addon-a11y": "6.0.17",
"@storybook/addon-actions": "6.0.17",
"@storybook/addon-essentials": "6.0.17",
"@storybook/addon-links": "6.0.17",
"@storybook/addon-storysource": "6.0.17",
"@storybook/react": "6.0.17",
"@types/react": "16.9.47",
"@types/react-dom": "16.9.8",
"@typescript-eslint/eslint-plugin": "3.9.1",
"@typescript-eslint/parser": "3.9.1",
"@typescript-eslint/eslint-plugin": "3.10.0",
"@typescript-eslint/parser": "3.10.0",
"babel-eslint": "10.1.0",
"babel-loader": "8.1.0",
"eslint": "7.7.0",
Expand All @@ -60,11 +60,11 @@
"gacp": "2.10.0",
"husky": "4.2.5",
"lint-staged": "10.2.11",
"prettier": "2.0.5",
"prettier": "2.1.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-is": "16.13.1",
"sort-package-json": "1.44.0",
"typescript": "3.9.7"
"typescript": "4.0.2"
}
}
6 changes: 2 additions & 4 deletions src/accordion/AccordionPanel.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/* eslint-disable no-unused-expressions */
/* eslint-disable react-hooks/exhaustive-deps */

import * as React from "react";
import { createComponent, createHook } from "reakit-system";
import {
Expand Down Expand Up @@ -37,6 +34,7 @@ export const useAccordionPanel = createHook<
if (!id) return undefined;

options.registerPanel?.({ id, ref });
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [id]);

const style = {
Expand All @@ -45,10 +43,10 @@ export const useAccordionPanel = createHook<
};

return {
ref: useForkRef(ref, htmlRef),
role: "region",
"aria-labelledby": `${buttonId ? buttonId : undefined}`,
style,
ref: useForkRef(ref, htmlRef),
...htmlProps,
};
},
Expand Down
122 changes: 63 additions & 59 deletions src/accordion/AccordionState.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,54 @@
import * as React from "react";

import { SealedInitialState, useSealedState } from "reakit-utils";
import {
unstable_IdInitialState,
unstable_IdStateReturn,
unstable_useIdState,
} from "reakit";
import { SealedInitialState, useSealedState } from "reakit-utils";

export type AccordionInitialState = unstable_IdInitialState & {
/**
* Allow to toggle multiple accordion items
*/
allowMultiple?: boolean;
};

export type Button = {
id: string;
ref: React.RefObject<HTMLElement>;
};

export type Panel = {
id: string;
ref: React.RefObject<HTMLElement>;
};

export type Item = {
id: string;
ref: React.RefObject<HTMLElement>;
button?: Button;
panel?: Panel;
};

export type AccordionState = {
items: Item[];
activeItems: string[];
buttons: Button[];
allowMultiple: boolean;
};

export type AccordionActions = {
registerItem: (item: Item) => void;
registerButton: (button: Button) => void;
registerPanel: (panel: Panel) => void;
addActiveItem: (id: string) => void;
removeActiveItem: (id: string) => void;
};

export type AccordionStateReturn = unstable_IdStateReturn &
AccordionState &
AccordionActions;

export function useAccordionState(
initialState: SealedInitialState<AccordionInitialState> = {},
Expand Down Expand Up @@ -42,6 +85,13 @@ export function useAccordionState(
};
}

export type AccordionReducerAction =
| { type: "registerItem"; item: Item }
| { type: "registerButton"; button: Button }
| { type: "registerPanel"; panel: Panel }
| { type: "addActiveItem"; id: string }
| { type: "removeActiveItem"; id: string };

function reducer(
state: AccordionState,
action: AccordionReducerAction,
Expand Down Expand Up @@ -71,11 +121,7 @@ function reducer(

case "registerButton": {
const { button } = action;
const item = items.find(r => r.ref.current?.contains(button.ref.current));
const nextItems = items.filter(
r => !r.ref.current?.contains(button.ref.current),
);
const nextItem = { ...item, button } as Item;
const { nextItem, nextItems } = getNextItem("button", button, items);

return {
...state,
Expand All @@ -86,11 +132,7 @@ function reducer(

case "registerPanel": {
const { panel } = action;
const item = items.find(r => r.ref.current?.contains(panel.ref.current));
const nextItems = items.filter(
r => !r.ref.current?.contains(panel.ref.current),
);
const nextItem = { ...item, panel } as Item;
const { nextItem, nextItems } = getNextItem("panel", panel, items);

return {
...state,
Expand All @@ -113,52 +155,14 @@ function reducer(
}
}

export type AccordionInitialState = unstable_IdInitialState & {
/**
* Allow to toggle multiple accordion items
*/
allowMultiple?: boolean;
};

export type Button = {
id: string;
ref: React.RefObject<HTMLElement>;
};

export type Panel = {
id: string;
ref: React.RefObject<HTMLElement>;
};

export type Item = {
id: string;
ref: React.RefObject<HTMLElement>;
button?: Button;
panel?: Panel;
};

export type AccordionState = {
items: Item[];
activeItems: string[];
buttons: Button[];
allowMultiple: boolean;
};
function getNextItem(type: string, currentItem: Button | Panel, items: Item[]) {
const item = items.find(r =>
r.ref.current?.contains(currentItem.ref.current),
);
const nextItems = items.filter(
r => !r.ref.current?.contains(currentItem.ref.current),
);
const nextItem = { ...item, [type]: currentItem } as Item;

export type AccordionActions = {
registerItem: (item: Item) => void;
registerButton: (button: Button) => void;
registerPanel: (panel: Panel) => void;
addActiveItem: (id: string) => void;
removeActiveItem: (id: string) => void;
};

export type AccordionStateReturn = unstable_IdStateReturn &
AccordionState &
AccordionActions;

export type AccordionReducerAction =
| { type: "registerItem"; item: Item }
| { type: "registerButton"; button: Button }
| { type: "registerPanel"; panel: Panel }
| { type: "addActiveItem"; id: string }
| { type: "removeActiveItem"; id: string };
return { nextItem, nextItems };
}
19 changes: 8 additions & 11 deletions src/accordion/AccordionTrigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
import * as React from "react";

import { createComponent, createHook } from "reakit-system";
import {
useForkRef,
useLiveRef,
createOnKeyDown,
isSelfTarget,
} from "reakit-utils";
import {
ButtonHTMLProps,
ButtonOptions,
unstable_IdHTMLProps,
unstable_IdOptions,
unstable_useId,
useButton,
} from "reakit";
import { useButton } from "reakit";
import {
useForkRef,
useLiveRef,
createOnKeyDown,
isSelfTarget,
} from "reakit-utils";

import { AccordionStateReturn } from "./AccordionState";
import { ACCORDION_KEYS } from "./__keys";
Expand All @@ -35,10 +35,6 @@ export const useAccordionTrigger = createHook<
keys: ACCORDION_KEYS,
compose: [useButton, unstable_useId],

useOptions(options, htmlProps) {
return { ...options };
},

useProps(
options,
{
Expand Down Expand Up @@ -133,5 +129,6 @@ export const useAccordionTrigger = createHook<

export const AccordionTrigger = createComponent({
as: "button",
memo: true,
useHook: useAccordionTrigger,
});
3 changes: 3 additions & 0 deletions src/accordion/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from "./AccordionState";
export * from "./Accordion";
export * from "./AccordionItem";
export * from "./AccordionTrigger";
export * from "./AccordionPanel";
4 changes: 2 additions & 2 deletions src/accordion/stories/Accordion.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const Default = () => {
<h3>
<AccordionTrigger {...state}>Trigger 3</AccordionTrigger>
</h3>
<AccordionPanel {...state}>Panel 4</AccordionPanel>
<AccordionPanel {...state}>Panel 3</AccordionPanel>
</AccordionItem>
</Accordion>
);
Expand All @@ -59,7 +59,7 @@ export const AllowMultiple = () => {
<h3>
<AccordionTrigger {...state}>Trigger 3</AccordionTrigger>
</h3>
<AccordionPanel {...state}>Panel 4</AccordionPanel>
<AccordionPanel {...state}>Panel 3</AccordionPanel>
</AccordionItem>
</Accordion>
);
Expand Down
23 changes: 2 additions & 21 deletions src/slider/SliderState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {
} from "@chakra-ui/utils";
import { ensureFocus } from "reakit-utils";

import { getDefaultValue, orient } from "./__utils";

export interface UseSliderProps {
/**
* The minimum allowed value of the slider. Cannot be greater than max.
Expand Down Expand Up @@ -487,25 +489,4 @@ export function useSliderState(props: UseSliderProps = {}) {
};
}

function orient(options: {
orientation: UseSliderProps["orientation"];
vertical: CSSProperties;
horizontal: CSSProperties;
}) {
const { orientation, vertical, horizontal } = options;

return orientation === "vertical" ? vertical : horizontal;
}

/**
* The browser <input type="range" /> calculates
* the default value of a slider by using mid-point
* between the min and the max.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range
*/
function getDefaultValue(min: number, max: number) {
return max < min ? min : min + (max - min) / 2;
}

export type UseSliderReturn = ReturnType<typeof useSliderState>;
4 changes: 2 additions & 2 deletions src/slider/SliderTrack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* to work with Reakit System
*/
import { createComponent, createHook } from "reakit-system";
import { mergeRefs, dataAttr } from "@chakra-ui/utils";
import { useId } from "@chakra-ui/hooks";
import { BoxHTMLProps, useBox } from "reakit";
import { useId } from "@chakra-ui/hooks";
import { mergeRefs, dataAttr } from "@chakra-ui/utils";

import { UseSliderReturn } from "./SliderState";
import { SLIDER_TRACK_KEYS } from "./__keys";
Expand Down
24 changes: 24 additions & 0 deletions src/slider/__utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { CSSProperties } from "react";

import { UseSliderProps } from "./SliderState";

export function orient(options: {
orientation: UseSliderProps["orientation"];
vertical: CSSProperties;
horizontal: CSSProperties;
}) {
const { orientation, vertical, horizontal } = options;

return orientation === "vertical" ? vertical : horizontal;
}

/**
* The browser <input type="range" /> calculates
* the default value of a slider by using mid-point
* between the min and the max.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range
*/
export function getDefaultValue(min: number, max: number) {
return max < min ? min : min + (max - min) / 2;
}
Loading

0 comments on commit 48c10fc

Please sign in to comment.