reshaped 2.11.0 → 2.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,10 +45,10 @@ const Actionable = forwardRef((props, ref) => {
45
45
  const isEnter = event.key === keys.ENTER;
46
46
  if (!isSpace && !isEnter)
47
47
  return;
48
- if (!renderedAsButton && hasClickHandler) {
49
- event.preventDefault();
50
- handlePress(event);
51
- }
48
+ if (rootAttributes.role !== "button")
49
+ return;
50
+ event.preventDefault();
51
+ handlePress(event);
52
52
  };
53
53
  return (_jsx(TagName, Object.assign({ ref: ref }, rootAttributes, { className: rootClassNames, onClick: handlePress, onKeyDown: handleKeyDown, children: children })));
54
54
  });
@@ -62,7 +62,7 @@ export const focusRing = () => (<Example>
62
62
  </Example.Item>
63
63
  </Example>);
64
64
  export const edgeCases = () => (<Example>
65
- <Example.Item title="insetFocus">
65
+ <Example.Item title="form submit">
66
66
  <form onSubmit={(e) => {
67
67
  e.preventDefault();
68
68
  alert("Submitted");
@@ -14,7 +14,7 @@ export default {
14
14
  };
15
15
  export const size = () => (<Example>
16
16
  <Example.Item title="size: small">
17
- <MenuItem size="small" icon={IconZap} href="#">
17
+ <MenuItem size="small" icon={IconZap} onClick={() => { }}>
18
18
  Menu item
19
19
  </MenuItem>
20
20
  </Example.Item>
@@ -57,8 +57,8 @@ const PinFieldControlled = (props) => {
57
57
  el.selectionStart = nextSelectionStart;
58
58
  el.selectionEnd = nextSelectionStart + 1;
59
59
  }
60
- setFocusedIndex(el.selectionStart);
61
- }, []);
60
+ setFocusedIndex(Math.min(el.selectionStart, valueLength - 1));
61
+ }, [valueLength]);
62
62
  /**
63
63
  * Using onNextFrame here to wait for the native behavior first
64
64
  */
@@ -15,8 +15,8 @@ export const base = () => (<Example>
15
15
  <PinField name="pin"/>
16
16
  </Example.Item>
17
17
 
18
- <Example.Item title="defaultValue: 12">
19
- <PinField name="pin2" defaultValue="12"/>
18
+ <Example.Item title="defaultValue: 1234">
19
+ <PinField name="pin2" defaultValue="1234"/>
20
20
  </Example.Item>
21
21
 
22
22
  <Example.Item title="value: 12">
@@ -7,17 +7,21 @@ import { onNextFrame } from "../../../utilities/animation.js";
7
7
  const Expandable = (props) => {
8
8
  const { children, active, attributes } = props;
9
9
  const [animated, setAnimated] = React.useState(false);
10
- const rootClassNames = classNames(s.root, active && s["--active"]);
10
+ const rootClassNames = classNames(s.root, active && animated && s["--active"], !active && !animated && s["--hidden"]);
11
11
  const handleTransitionEnd = (e) => {
12
12
  if (e.propertyName !== "height")
13
13
  return;
14
+ if (active)
15
+ return;
14
16
  onNextFrame(() => {
15
17
  setAnimated(false);
16
18
  });
17
19
  };
18
20
  React.useEffect(() => {
19
- setAnimated(active || false);
21
+ if (!active)
22
+ return;
23
+ setAnimated(active);
20
24
  }, [active]);
21
- return (_jsx("div", Object.assign({}, attributes, { className: rootClassNames, onTransitionEnd: handleTransitionEnd, role: "region", hidden: !active && !animated, children: _jsx("div", { className: s.inner, children: children }) })));
25
+ return (_jsx("div", Object.assign({}, attributes, { className: rootClassNames, onTransitionEnd: handleTransitionEnd, role: "region", hidden: !active, children: _jsx("div", { className: s.inner, children: children }) })));
22
26
  };
23
27
  export default Expandable;
@@ -1 +1 @@
1
- .root{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--rs-duration-slow) var(--rs-easing-standard)}.--active{grid-template-rows:1fr}.inner{overflow:hidden}
1
+ .root{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--rs-duration-slow) var(--rs-easing-standard)}.--active{grid-template-rows:1fr}.--hidden{display:none}.inner{overflow:hidden}
@@ -71,6 +71,7 @@ export type ContextProps = {
71
71
  handleMouseEnter: () => void;
72
72
  handleMouseLeave: () => void;
73
73
  handleTransitionEnd: (e: React.TransitionEvent) => void;
74
+ handleTransitionStart: (e: TransitionEvent) => void;
74
75
  handleClick: () => void;
75
76
  handleBlur: (e: React.FocusEvent) => void;
76
77
  handleFocus: () => void;
@@ -9,12 +9,22 @@ import { useFlyoutContext } from "./Flyout.context.js";
9
9
  import s from "./Flyout.module.css";
10
10
  const FlyoutContent = (props) => {
11
11
  const { children, className, attributes } = props;
12
- const { flyout, id, flyoutElRef, triggerElRef, handleTransitionEnd, triggerType, handleMouseEnter, handleMouseLeave, handleContentMouseDown, handleContentMouseUp, contentGap, contentClassName, contentAttributes, trapFocusMode, width, } = useFlyoutContext();
12
+ const { flyout, id, flyoutElRef, triggerElRef, handleTransitionEnd, handleTransitionStart, triggerType, handleMouseEnter, handleMouseLeave, handleContentMouseDown, handleContentMouseUp, contentGap, contentClassName, contentAttributes, trapFocusMode, width, } = useFlyoutContext();
13
13
  const { styles, status, position } = flyout;
14
14
  const [mounted, setMounted] = React.useState(false);
15
15
  useIsomorphicLayoutEffect(() => {
16
16
  setMounted(true);
17
17
  }, []);
18
+ /**
19
+ * transitionStart doesn't exist as a jsx event handler and needs to be handled with vanilla js
20
+ */
21
+ React.useEffect(() => {
22
+ const el = flyoutElRef.current;
23
+ if (!el)
24
+ return;
25
+ el.addEventListener("transitionstart", handleTransitionStart);
26
+ return () => el.removeEventListener("transitionstart", handleTransitionStart);
27
+ }, [handleTransitionStart, flyoutElRef, status]);
18
28
  if (status === "idle" || !mounted)
19
29
  return null;
20
30
  const contentClassNames = classNames(s.content, status === "visible" && s["--visible"],
@@ -22,6 +22,7 @@ const FlyoutRoot = (props) => {
22
22
  const timerRef = React.useRef();
23
23
  const trapFocusRef = React.useRef(null);
24
24
  const lockedRef = React.useRef(false);
25
+ const transitionStartedRef = React.useRef(false);
25
26
  const lockedBlurEffects = React.useRef(false);
26
27
  const shouldReturnFocusRef = React.useRef(true);
27
28
  const flyout = useFlyout(triggerElRef, flyoutElRef, {
@@ -108,19 +109,33 @@ const FlyoutRoot = (props) => {
108
109
  render();
109
110
  return;
110
111
  }
111
- if (checkTransitions() && !disableHideAnimation) {
112
+ /**
113
+ * Check that transitions are enabled and it has been triggered on tooltip open
114
+ * (keyboard focus navigation could move too fast and ignore the transitions completely)
115
+ */
116
+ if (checkTransitions() && !disableHideAnimation && transitionStartedRef.current) {
112
117
  hide();
113
- // In case transitions are disabled globally - remove from the DOM immediately
114
118
  }
115
119
  else {
120
+ // In case transitions are disabled globally - remove from the DOM immediately
116
121
  remove();
117
122
  }
118
123
  }, [passedActive, render, hide, disableHideAnimation]);
124
+ const handleTransitionStart = React.useCallback((e) => {
125
+ if (!passedActive)
126
+ return;
127
+ if (flyoutElRef.current !== e.currentTarget || e.propertyName !== "transform")
128
+ return;
129
+ console.log("fofoo");
130
+ transitionStartedRef.current = true;
131
+ }, [passedActive]);
119
132
  const handleTransitionEnd = React.useCallback((e) => {
120
133
  if (flyoutElRef.current !== e.currentTarget || e.propertyName !== "transform")
121
134
  return;
122
- if (status === "hidden")
135
+ if (status === "hidden") {
136
+ transitionStartedRef.current = false;
123
137
  remove();
138
+ }
124
139
  }, [remove, status]);
125
140
  /**
126
141
  * Handle focus trap
@@ -203,6 +218,7 @@ const FlyoutRoot = (props) => {
203
218
  handleBlur,
204
219
  handleMouseEnter,
205
220
  handleMouseLeave,
221
+ handleTransitionStart,
206
222
  handleTransitionEnd,
207
223
  handleClick: handleTriggerClick,
208
224
  handleContentMouseDown,
@@ -212,9 +212,10 @@ const flyoutReducer = (state, action) => {
212
212
  case "position":
213
213
  return Object.assign(Object.assign({}, state), { status: state.status === "visible" ? "visible" : "positioned", position: action.payload.position, styles: Object.assign(Object.assign({}, defaultStyles), action.payload.styles) });
214
214
  case "show":
215
- return Object.assign(Object.assign({}, state), { status: "visible" });
215
+ return state.status === "positioned"
216
+ ? Object.assign(Object.assign({}, state), { status: "visible" }) : Object.assign(Object.assign({}, state), { status: "idle" });
216
217
  case "hide":
217
- return Object.assign(Object.assign({}, state), { status: state.status === "idle" ? "idle" : "hidden" });
218
+ return Object.assign(Object.assign({}, state), { status: state.status === "idle" || state.status === "hidden" ? "idle" : "hidden" });
218
219
  case "remove":
219
220
  return Object.assign(Object.assign({}, state), { status: "idle", styles: resetStyles });
220
221
  default:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "reshaped",
3
3
  "description": "Professionally crafted design system in React & Figma for building products of any scale and complexity",
4
- "version": "2.11.0",
4
+ "version": "2.11.2",
5
5
  "license": "MIT",
6
6
  "email": "hello@reshaped.so",
7
7
  "homepage": "https://reshaped.so",