@cypress-design/react-docmenu 0.4.3 → 0.5.0

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.
package/dist/index.es.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { createContext } from 'react';
2
3
  import clsx from 'clsx';
3
4
  import * as iconsRegistry from '@cypress-design/icon-registry';
4
5
  import { ICON_COLOR_PROP_NAMES } from '@cypress-design/icon-registry';
@@ -154,18 +155,23 @@ var IconChevronDownSmall = function (props) { return React.createElement('svg',
154
155
  /* <wind-keep class="filter icon-light-secondary icon-dark-secondary"> */
155
156
 
156
157
  const classes = {
158
+ expandedIcon: 'absolute left-0 transform transition-transform text-gray-400 dark:text-gray-700',
157
159
  button: 'flex leading-[24px] py-[10px] items-center relative w-full text-start',
158
160
  topButton: 'leading-[24px] text-[16px] pl-[24px] font-medium',
159
- leafButton: 'leading-[20px] text-[14px] pl-[40px]',
161
+ leafButton: 'leading-[20px] text-[14px] pl-[48px]',
162
+ openListBorderLeft: 'absolute left-[8px] top-0 w-[1px] h-full bg-gray-100 dark:bg-gray-900',
160
163
  };
161
164
 
165
+ var MarkerIsMovingContext = createContext({
166
+ setMarkerIsMoving: function () { },
167
+ markerIsMoving: false,
168
+ });
169
+
162
170
  var DocLink = React.forwardRef(function (_a, ref) {
163
171
  var item = _a.item, active = _a.active, collapsible = _a.collapsible, _b = _a.depth, depth = _b === void 0 ? -1 : _b, onActive = _a.onActive, _c = _a.LinkComponent, LinkComponent = _c === void 0 ? 'a' : _c;
164
172
  var activeLIRef = React.useRef(null);
165
- // on mount, if the item is active,
166
- // send the top position to the parent
167
- React.useEffect(setActiveMarkerPosition, [onActive, active]);
168
- function setActiveMarkerPosition() {
173
+ var _d = React.useContext(MarkerIsMovingContext), markerIsMoving = _d.markerIsMoving, setMarkerIsMoving = _d.setMarkerIsMoving;
174
+ var setActiveMarkerPosition = function () {
169
175
  var _a;
170
176
  if (active) {
171
177
  var box = (_a = activeLIRef === null || activeLIRef === void 0 ? void 0 : activeLIRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
@@ -174,31 +180,51 @@ var DocLink = React.forwardRef(function (_a, ref) {
174
180
  height: (box === null || box === void 0 ? void 0 : box.height) || 0,
175
181
  });
176
182
  }
177
- }
183
+ };
184
+ // on mount, if the item is active,
185
+ // send the top position to the parent
186
+ React.useEffect(setActiveMarkerPosition, [
187
+ onActive,
188
+ active,
189
+ setMarkerIsMoving,
190
+ ]);
178
191
  React.useImperativeHandle(ref, function () { return ({
179
192
  setActiveMarkerPosition: setActiveMarkerPosition,
180
193
  }); });
181
- return (React.createElement("li", { ref: activeLIRef, className: clsx('list-none p-0', {
182
- 'pl-[16px]': depth >= 0,
183
- }) },
184
- React.createElement(LinkComponent, { className: clsx('group relative inline-block pl-[24px]', {
194
+ return (React.createElement("li", { ref: activeLIRef, className: "list-none p-0" },
195
+ React.createElement(LinkComponent, { className: clsx('group relative block w-full pl-[24px]', {
185
196
  'text-indigo-500': active,
197
+ 'text-gray-700 dark:text-gray-500': !active,
186
198
  'py-[8px] text-[16px] leading-[24px]': depth < 0,
187
- 'py-[12px] leading-[20px] text-[14px]': depth >= 0,
188
- }), href: item.href },
189
- depth >= 0 ? (React.createElement("div", { className: clsx('absolute w-[4px] z-10 top-[4px] bottom-[4px] rounded-full hidden', {
199
+ 'leading-[20px] text-[14px] py-[12px]': depth >= 0,
200
+ }), href: item.href, style: {
201
+ paddingLeft: depth >= 0 ? "".concat(depth * 12 + 48, "px") : undefined,
202
+ } },
203
+ depth >= 0 ? (React.createElement("div", { className: clsx('left-[6.5px] absolute top-[4px] bottom-[4px] w-[4px] z-10 rounded-full', {
204
+ hidden: !markerIsMoving || !active,
190
205
  'group-hover:block bg-gray-300': !active && collapsible,
191
- }), style: {
192
- left: "-".concat(18.5 + depth * 8, "px"),
193
- } })) : null,
206
+ 'bg-indigo-500': active && markerIsMoving,
207
+ }) })) : null,
194
208
  item.label)));
195
209
  });
196
210
 
211
+ var useIsMounted = function () {
212
+ var isMounted = React.useRef(false);
213
+ React.useEffect(function () {
214
+ isMounted.current = true;
215
+ return function () {
216
+ isMounted.current = false;
217
+ };
218
+ }, []);
219
+ return isMounted;
220
+ };
197
221
  var DocGroup = React.forwardRef(function (_a, ref) {
198
222
  var _b;
199
223
  var group = _a.group, activePath = _a.activePath, collapsible = _a.collapsible, _c = _a.depth, depth = _c === void 0 ? 0 : _c, onActivePosition = _a.onActivePosition, updateMarkerPosition = _a.updateMarkerPosition, _d = _a.LinkComponent, LinkComponent = _d === void 0 ? 'a' : _d, hideMarker = _a.hideMarker;
200
224
  var _e = React.useState(group.collapsed !== true), open = _e[0], setOpen = _e[1];
201
225
  var $groupElements = React.useRef(null);
226
+ var $listWrapper = React.useRef(null);
227
+ var didMount = useIsMounted();
202
228
  function toggleMenu(open) {
203
229
  if (!collapsible)
204
230
  return;
@@ -220,29 +246,58 @@ var DocGroup = React.forwardRef(function (_a, ref) {
220
246
  onActivePosition({ top: top, height: height });
221
247
  }
222
248
  }, [onActivePosition, open]);
223
- function reTriggerSetActiveGroup() {
249
+ var setMarkerIsMoving = React.useContext(MarkerIsMovingContext).setMarkerIsMoving;
250
+ function reTriggerSetActiveGroupParent() {
224
251
  var _a;
225
252
  (_a = $groupElements.current) === null || _a === void 0 ? void 0 : _a.reTriggerSetActiveGroup();
226
253
  }
227
254
  React.useEffect(function () {
228
- if (hasActiveItemRecursively()) {
229
- if (open) {
230
- reTriggerSetActiveGroup();
255
+ var _a, _b;
256
+ if (didMount.current) {
257
+ (_a = $listWrapper.current) === null || _a === void 0 ? void 0 : _a.addEventListener('transitionstart', function () {
258
+ setMarkerIsMoving(true);
259
+ }, { once: true });
260
+ (_b = $listWrapper.current) === null || _b === void 0 ? void 0 : _b.addEventListener('transitionend', function () {
261
+ setMarkerIsMoving(false);
262
+ if (open || !hasActiveItemRecursively()) {
263
+ updateMarkerPosition === null || updateMarkerPosition === void 0 ? void 0 : updateMarkerPosition();
264
+ }
265
+ }, { once: true });
266
+ }
267
+ }, [
268
+ open,
269
+ setMarkerIsMoving,
270
+ updateMarkerPosition,
271
+ hasActiveItemRecursively,
272
+ didMount,
273
+ ]);
274
+ React.useEffect(function () {
275
+ if (didMount.current) {
276
+ if (hasActiveItemRecursively()) {
277
+ if (open) {
278
+ reTriggerSetActiveGroupParent();
279
+ }
280
+ else {
281
+ hideMarker();
282
+ }
231
283
  }
232
284
  else {
233
- hideMarker();
285
+ updateMarkerPosition === null || updateMarkerPosition === void 0 ? void 0 : updateMarkerPosition();
234
286
  }
235
287
  }
236
- else {
237
- updateMarkerPosition === null || updateMarkerPosition === void 0 ? void 0 : updateMarkerPosition();
238
- }
239
- }, [open, updateMarkerPosition, hideMarker, hasActiveItemRecursively]);
288
+ }, [
289
+ open,
290
+ updateMarkerPosition,
291
+ hideMarker,
292
+ hasActiveItemRecursively,
293
+ didMount,
294
+ ]);
240
295
  React.useImperativeHandle(ref, function () { return ({
241
- reTriggerSetActiveGroup: reTriggerSetActiveGroup,
296
+ reTriggerSetActiveGroup: reTriggerSetActiveGroupParent,
242
297
  }); });
243
298
  var onUpdateMarkerPosition = React.useCallback(function () {
244
299
  if (hasActiveItemRecursively()) {
245
- reTriggerSetActiveGroup();
300
+ reTriggerSetActiveGroupParent();
246
301
  }
247
302
  else {
248
303
  updateMarkerPosition === null || updateMarkerPosition === void 0 ? void 0 : updateMarkerPosition();
@@ -254,13 +309,18 @@ var DocGroup = React.forwardRef(function (_a, ref) {
254
309
  _b[classes.leafButton] = depth,
255
310
  _b['text-indigo-500'] = activePath === group.href,
256
311
  _b)) },
257
- collapsible ? (React.createElement(IconChevronDownSmall, { "stroke-color": "gray-400", size: depth ? '8' : '16', className: clsx('absolute transform transition-transform left-0', {
312
+ collapsible ? (React.createElement(IconChevronDownSmall, { "stroke-color": "gray-400", size: depth ? '8' : '16', className: clsx(classes.expandedIcon, {
258
313
  'rotate-0': open,
259
314
  '-rotate-90': !open,
260
- 'ml-[16px]': depth,
315
+ 'ml-[28px]': depth,
261
316
  }) })) : null,
262
317
  group.label),
263
- React.createElement(DocGroupElements, { ref: $groupElements, className: !open ? 'hidden' : undefined, items: group.items, activePath: activePath, collapsible: collapsible, depth: depth, onActivePosition: setActivePosition, updateMarkerPosition: onUpdateMarkerPosition, LinkComponent: LinkComponent, hideMarker: hideMarker })));
318
+ React.createElement("div", { className: clsx('grid transition-all relative', {
319
+ 'grid-rows-[0fr]': !open && collapsible,
320
+ 'grid-rows-[1fr]': open || !collapsible,
321
+ }), ref: $listWrapper },
322
+ open && collapsible && depth === 0 ? (React.createElement("div", { className: classes.openListBorderLeft })) : null,
323
+ React.createElement(DocGroupElements, { ref: $groupElements, className: "overflow-hidden", items: group.items, activePath: activePath, collapsible: collapsible, depth: depth, onActivePosition: setActivePosition, updateMarkerPosition: onUpdateMarkerPosition, LinkComponent: LinkComponent, hideMarker: hideMarker }))));
264
324
  });
265
325
  var DocGroupElements = React.forwardRef(function (_a, ref) {
266
326
  var items = _a.items, activePath = _a.activePath, collapsible = _a.collapsible, _b = _a.depth, depth = _b === void 0 ? 0 : _b, onActivePosition = _a.onActivePosition, updateMarkerPosition = _a.updateMarkerPosition, LinkComponent = _a.LinkComponent, hideMarker = _a.hideMarker, className = _a.className, rest = __rest$1(_a, ["items", "activePath", "collapsible", "depth", "onActivePosition", "updateMarkerPosition", "LinkComponent", "hideMarker", "className"]);
@@ -275,35 +335,42 @@ var DocGroupElements = React.forwardRef(function (_a, ref) {
275
335
  return item.href === activePath;
276
336
  });
277
337
  }, [items, activePath]);
278
- function reTriggerSetActiveGroup() {
279
- $groups.current.forEach(function (group) {
280
- group === null || group === void 0 ? void 0 : group.reTriggerSetActiveGroup();
281
- });
338
+ var reTriggerSetActiveGroup = React.useCallback(function (index) {
339
+ if (index === void 0) { index = 0; }
282
340
  $items.current.forEach(function (item) {
283
341
  item === null || item === void 0 ? void 0 : item.setActiveMarkerPosition();
284
342
  });
285
- }
343
+ // calculate the index of the calling group in the list of groups
344
+ var indexGroup = index -
345
+ // remove all the items that are not groups from the array and count them
346
+ items.slice(0, index).filter(function (item) { return !('items' in item); }).length;
347
+ // only update groups that come after the toggled one
348
+ // others will not need to update the marker
349
+ // since they are "before" in the rendering tree
350
+ $groups.current.slice(indexGroup + 1).forEach(function (group) {
351
+ group === null || group === void 0 ? void 0 : group.reTriggerSetActiveGroup();
352
+ });
353
+ }, [items]);
286
354
  React.useImperativeHandle(ref, function () { return ({
287
355
  reTriggerSetActiveGroup: reTriggerSetActiveGroup,
288
356
  }); });
289
- var onUpdateMarkerPosition = React.useCallback(function () {
357
+ var onUpdateMarkerPosition = React.useCallback(function (index) {
290
358
  if (hasActiveItemRecursively()) {
291
- reTriggerSetActiveGroup();
359
+ reTriggerSetActiveGroup(index);
292
360
  }
293
361
  else {
294
362
  updateMarkerPosition === null || updateMarkerPosition === void 0 ? void 0 : updateMarkerPosition();
295
363
  }
296
- }, [hasActiveItemRecursively, updateMarkerPosition]);
297
- return (React.createElement("ul", __assign$1({}, rest, { className: clsx('list-none p-0', className, {
298
- 'border-l border-gray-100': depth === 0 && collapsible,
299
- 'ml-[8px]': depth >= 0,
300
- }) }), items.map(function (item, index) {
364
+ }, [hasActiveItemRecursively, updateMarkerPosition, reTriggerSetActiveGroup]);
365
+ return (React.createElement("ul", __assign$1({}, rest, { className: clsx('list-none p-0', className) }), items.map(function (item, index) {
301
366
  return 'items' in item ? (React.createElement("li", { key: index, className: "relative list-none p-0" },
302
367
  React.createElement(DocGroup, { ref: function (el) {
303
368
  $groups.current[index] = el;
304
- }, group: item, activePath: activePath, depth: depth + 1, collapsible: collapsible, LinkComponent: LinkComponent, hideMarker: hideMarker, onActivePosition: onActivePosition, updateMarkerPosition: onUpdateMarkerPosition }))) : (React.createElement(DocLink, { ref: function (el) {
369
+ }, group: item, activePath: activePath, depth: depth + 1, collapsible: collapsible, LinkComponent: LinkComponent, hideMarker: hideMarker, onActivePosition: onActivePosition, updateMarkerPosition: function () { return onUpdateMarkerPosition(index); } }))) : (React.createElement(DocLink, { ref: function (el) {
305
370
  $items.current[index] = el;
306
- }, key: index, item: item, active: item.href === activePath, collapsible: collapsible, depth: depth, onActive: onActivePosition, LinkComponent: LinkComponent }));
371
+ }, key: index, item: item, active: item.href === activePath, collapsible: collapsible, depth: depth, onActive: function (opts) {
372
+ return depth < 0 ? hideMarker() : onActivePosition(opts);
373
+ }, LinkComponent: LinkComponent }));
307
374
  })));
308
375
  });
309
376
 
@@ -312,6 +379,7 @@ var DocMenu = function (_a) {
312
379
  var _e = React.useState(0), activeTop = _e[0], setActiveTop = _e[1];
313
380
  var _f = React.useState(36), activeHeight = _f[0], setActiveHeight = _f[1];
314
381
  var _g = React.useState(false), showMarker = _g[0], setShowMarker = _g[1];
382
+ var _h = React.useState(false), markerIsMoving = _h[0], setMarkerIsMoving = _h[1];
315
383
  var container = React.useRef(null);
316
384
  var setActivePosition = React.useCallback(function (opts) {
317
385
  var _a;
@@ -320,15 +388,17 @@ var DocMenu = function (_a) {
320
388
  setActiveTop(opts.top - containerTop);
321
389
  setActiveHeight(opts.height);
322
390
  }, []);
323
- return (React.createElement("div", { ref: container, className: "relative" },
324
- showMarker && collapsible ? (React.createElement("div", { className: "absolute h-[36px] w-[4px] z-50 rounded-full bg-indigo-500 transition-all duration-300 ml-[6.5px] mt-[4px]", style: {
325
- top: "".concat(activeTop + 4, "px"),
326
- height: "".concat(activeHeight - 8, "px"),
327
- } })) : null,
328
- React.createElement(DocGroupElements, __assign$1({}, rest, { items: items, activePath: activePath, collapsible: collapsible, depth: -1, onActivePosition: setActivePosition, LinkComponent: LinkComponent, hideMarker: function () { return setShowMarker(false); } }))));
391
+ var setShowMarkerFalse = React.useCallback(function () { return setShowMarker(false); }, []);
392
+ return (React.createElement(MarkerIsMovingContext.Provider, { value: { markerIsMoving: markerIsMoving, setMarkerIsMoving: setMarkerIsMoving } },
393
+ React.createElement("div", { ref: container, className: "relative" },
394
+ showMarker && !markerIsMoving && collapsible ? (React.createElement("div", { className: "absolute h-[36px] w-[4px] z-50 rounded-full bg-indigo-500 transition-all duration-300 ml-[6.5px] mt-[4px]", style: {
395
+ top: "".concat(activeTop, "px"),
396
+ height: "".concat(activeHeight - 8, "px"),
397
+ } })) : null,
398
+ React.createElement(DocGroupElements, __assign$1({}, rest, { items: items, activePath: activePath, collapsible: collapsible, depth: -1, onActivePosition: setActivePosition, LinkComponent: LinkComponent, hideMarker: setShowMarkerFalse })))));
329
399
  };
330
400
 
331
401
  export { DocMenu as default };
332
402
  //# sourceMappingURL=index.es.mjs.map
333
403
 
334
- /* <wind-keep class="container relative absolute h-[36px] w-[4px] z-50 rounded-full bg-indigo-500 transition-all duration-300 ml-[6.5px] mt-[4px] text-indigo-500 transform transition-transform left-0 rotate-0 -rotate-90 ml-[16px] hidden list-none p-0 border-l border-gray-100 ml-[8px] pl-[16px] inline-block pl-[24px] py-[8px] text-[16px] leading-[24px] py-[12px] leading-[20px] text-[14px] z-10 top-[4px] bottom-[4px] group-hover:block bg-gray-300 flex py-[10px] items-center w-full text-start font-medium pl-[40px]"> */
404
+ /* <wind-keep class="container relative absolute h-[36px] w-[4px] z-50 rounded-full bg-indigo-500 transition-all duration-300 ml-[6.5px] mt-[4px] text-indigo-500 rotate-0 -rotate-90 ml-[28px] grid grid-rows-[0fr] grid-rows-[1fr] overflow-hidden filter list-none p-0 block w-full pl-[24px] text-gray-700 dark:text-gray-500 py-[8px] text-[16px] leading-[24px] leading-[20px] text-[14px] py-[12px] left-[6.5px] top-[4px] bottom-[4px] z-10 hidden group-hover:block bg-gray-300 text-gray-500 left-0 transform transition-transform text-gray-400 dark:text-gray-700 flex py-[10px] items-center text-start font-medium pl-[48px] left-[8px] top-0 w-[1px] h-full bg-gray-100 dark:bg-gray-900"> */