@stoplight/elements-core 9.0.12 → 9.0.13

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.
@@ -21,6 +21,7 @@ export declare type TableOfContentsGroup = {
21
21
  title: string;
22
22
  items: TableOfContentsGroupItem[];
23
23
  itemsType?: 'article' | 'http_operation' | 'http_webhook' | 'model';
24
+ index: string;
24
25
  };
25
26
  export declare type TableOfContentsExternalLink = {
26
27
  title: string;
@@ -33,5 +34,11 @@ export declare type TableOfContentsNode<T = 'http_service' | 'http_operation' |
33
34
  type: T;
34
35
  meta: string;
35
36
  version?: string;
37
+ index: string;
36
38
  };
37
39
  export declare type TableOfContentsNodeGroup = TableOfContentsNode<'http_service'> & TableOfContentsGroup;
40
+ export declare type ActiveItemContextType = {
41
+ activeId: string | undefined;
42
+ lastActiveIndex: string;
43
+ setLastActiveIndex: React.Dispatch<React.SetStateAction<string>>;
44
+ };
package/index.esm.js CHANGED
@@ -3496,7 +3496,7 @@ function findFirstNode(items) {
3496
3496
  return;
3497
3497
  }
3498
3498
  function isDivider(item) {
3499
- return Object.keys(item).length === 1 && 'title' in item;
3499
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3500
3500
  }
3501
3501
  function isGroup(item) {
3502
3502
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3508,13 +3508,33 @@ function isNode(item) {
3508
3508
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3509
3509
  }
3510
3510
  function isExternalLink(item) {
3511
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3511
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3512
3512
  }
3513
3513
 
3514
- const ActiveIdContext = React.createContext(undefined);
3514
+ const ActiveItemContext = React.createContext({
3515
+ activeId: undefined,
3516
+ lastActiveIndex: '',
3517
+ setLastActiveIndex: () => { },
3518
+ });
3515
3519
  const LinkContext = React.createContext(undefined);
3516
3520
  LinkContext.displayName = 'LinkContext';
3517
3521
  const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3522
+ const [lastActiveIndex, setLastActiveIndex] = useState('');
3523
+ const value = React.useMemo(() => ({
3524
+ lastActiveIndex,
3525
+ setLastActiveIndex,
3526
+ activeId,
3527
+ }), [lastActiveIndex, activeId]);
3528
+ const updateTocTree = React.useCallback((arr, parentId) => {
3529
+ return arr.map((item, key) => {
3530
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3531
+ if (isGroup(item) || isNodeGroup(item)) {
3532
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3533
+ }
3534
+ return newItem;
3535
+ });
3536
+ }, []);
3537
+ const updatedTree = updateTocTree(tree, '');
3518
3538
  const container = React.useRef(null);
3519
3539
  const child = React.useRef(null);
3520
3540
  const firstRender = useFirstRender();
@@ -3534,18 +3554,30 @@ const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefaul
3534
3554
  return (React.createElement(Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3535
3555
  React.createElement(Box, { ref: child, my: 3 },
3536
3556
  React.createElement(LinkContext.Provider, { value: Link },
3537
- React.createElement(ActiveIdContext.Provider, { value: activeId }, tree.map((item, key) => {
3538
- if (isDivider(item)) {
3539
- return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3540
- }
3541
- return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3542
- }))))));
3557
+ React.createElement(ActiveItemContext.Provider, { value: value },
3558
+ React.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3559
+ if (isDivider(item)) {
3560
+ return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3561
+ }
3562
+ return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3563
+ })))))));
3543
3564
  });
3544
3565
  TableOfContents.displayName = 'TableOfContents';
3545
3566
  const Divider = React.memo(({ item, isInResponsiveMode = false }) => {
3546
3567
  return (React.createElement(Box, { pl: 4, mb: 2, mt: 6, textTransform: "uppercase", fontSize: isInResponsiveMode ? 'lg' : 'sm', lineHeight: "relaxed", letterSpacing: "wide", fontWeight: "bold" }, item.title));
3547
3568
  });
3548
3569
  Divider.displayName = 'Divider';
3570
+ const TOCContainer = React.memo(({ children, updatedTree }) => {
3571
+ const { setLastActiveIndex } = React.useContext(ActiveItemContext);
3572
+ React.useEffect(() => {
3573
+ const firstNode = findFirstNode(updatedTree);
3574
+ if (firstNode) {
3575
+ setLastActiveIndex(firstNode.index);
3576
+ }
3577
+ }, []);
3578
+ return React.createElement(Box, null, children);
3579
+ });
3580
+ TOCContainer.displayName = 'TOCContainer';
3549
3581
  const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3550
3582
  if (isExternalLink(item)) {
3551
3583
  return (React.createElement(Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3563,9 +3595,24 @@ const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsi
3563
3595
  });
3564
3596
  GroupItem.displayName = 'GroupItem';
3565
3597
  const Group = React.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3566
- const activeId = React.useContext(ActiveIdContext);
3598
+ const { activeId, lastActiveIndex } = React.useContext(ActiveItemContext);
3567
3599
  const [isOpen, setIsOpen] = React.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3568
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3600
+ const isActiveGroup = React.useCallback((items, activeId, contextIndex) => {
3601
+ return items.some(element => {
3602
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3603
+ const hasItems = 'items' in element && Array.isArray(element.items);
3604
+ if (!hasSlugOrId && !hasItems)
3605
+ return false;
3606
+ if (activeId &&
3607
+ 'index' in element &&
3608
+ (element.slug === activeId || element.id === activeId) &&
3609
+ element.index === contextIndex) {
3610
+ return true;
3611
+ }
3612
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3613
+ });
3614
+ }, []);
3615
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3569
3616
  React.useEffect(() => {
3570
3617
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3571
3618
  if (isOpen !== openByDefault) {
@@ -3615,8 +3662,10 @@ const Item = React.memo(({ depth, isActive, id, title, meta, icon, isInResponsiv
3615
3662
  });
3616
3663
  Item.displayName = 'Item';
3617
3664
  const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode, onClick, onLinkClick = () => { } }) => {
3618
- const activeId = React.useContext(ActiveIdContext);
3619
- const isActive = activeId === item.slug || activeId === item.id;
3665
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React.useContext(ActiveItemContext);
3666
+ const { index } = item;
3667
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3668
+ const isActive = lastActiveIndex === index && isSlugMatched;
3620
3669
  const LinkComponent = React.useContext(LinkContext);
3621
3670
  const handleClick = (e) => {
3622
3671
  if (isActive) {
@@ -3624,6 +3673,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3624
3673
  e.preventDefault();
3625
3674
  }
3626
3675
  else {
3676
+ setLastActiveIndex(index);
3627
3677
  onLinkClick();
3628
3678
  }
3629
3679
  if (onClick) {
@@ -3631,7 +3681,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3631
3681
  }
3632
3682
  };
3633
3683
  return (React.createElement(Box, { as: LinkComponent, to: resolveRelativeLink(item.slug), display: "block", textDecoration: "no-underline", className: "ElementsTableOfContentsItem" },
3634
- React.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React.createElement(Box, { as: Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: handleClick })));
3684
+ React.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React.createElement(Box, { as: Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: e => handleClick(e) })));
3635
3685
  });
3636
3686
  Node.displayName = 'Node';
3637
3687
  const Version = ({ value }) => {
package/index.js CHANGED
@@ -3517,7 +3517,7 @@ function findFirstNode(items) {
3517
3517
  return;
3518
3518
  }
3519
3519
  function isDivider(item) {
3520
- return Object.keys(item).length === 1 && 'title' in item;
3520
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3521
3521
  }
3522
3522
  function isGroup(item) {
3523
3523
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3529,13 +3529,33 @@ function isNode(item) {
3529
3529
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3530
3530
  }
3531
3531
  function isExternalLink(item) {
3532
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3532
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3533
3533
  }
3534
3534
 
3535
- const ActiveIdContext = React__namespace.createContext(undefined);
3535
+ const ActiveItemContext = React__namespace.createContext({
3536
+ activeId: undefined,
3537
+ lastActiveIndex: '',
3538
+ setLastActiveIndex: () => { },
3539
+ });
3536
3540
  const LinkContext = React__namespace.createContext(undefined);
3537
3541
  LinkContext.displayName = 'LinkContext';
3538
3542
  const TableOfContents = React__namespace.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3543
+ const [lastActiveIndex, setLastActiveIndex] = React.useState('');
3544
+ const value = React__namespace.useMemo(() => ({
3545
+ lastActiveIndex,
3546
+ setLastActiveIndex,
3547
+ activeId,
3548
+ }), [lastActiveIndex, activeId]);
3549
+ const updateTocTree = React__namespace.useCallback((arr, parentId) => {
3550
+ return arr.map((item, key) => {
3551
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3552
+ if (isGroup(item) || isNodeGroup(item)) {
3553
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3554
+ }
3555
+ return newItem;
3556
+ });
3557
+ }, []);
3558
+ const updatedTree = updateTocTree(tree, '');
3539
3559
  const container = React__namespace.useRef(null);
3540
3560
  const child = React__namespace.useRef(null);
3541
3561
  const firstRender = useFirstRender();
@@ -3555,18 +3575,30 @@ const TableOfContents = React__namespace.memo(({ tree, activeId, Link, maxDepthO
3555
3575
  return (React__namespace.createElement(mosaic.Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3556
3576
  React__namespace.createElement(mosaic.Box, { ref: child, my: 3 },
3557
3577
  React__namespace.createElement(LinkContext.Provider, { value: Link },
3558
- React__namespace.createElement(ActiveIdContext.Provider, { value: activeId }, tree.map((item, key) => {
3559
- if (isDivider(item)) {
3560
- return React__namespace.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3561
- }
3562
- return (React__namespace.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3563
- }))))));
3578
+ React__namespace.createElement(ActiveItemContext.Provider, { value: value },
3579
+ React__namespace.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3580
+ if (isDivider(item)) {
3581
+ return React__namespace.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3582
+ }
3583
+ return (React__namespace.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3584
+ })))))));
3564
3585
  });
3565
3586
  TableOfContents.displayName = 'TableOfContents';
3566
3587
  const Divider = React__namespace.memo(({ item, isInResponsiveMode = false }) => {
3567
3588
  return (React__namespace.createElement(mosaic.Box, { pl: 4, mb: 2, mt: 6, textTransform: "uppercase", fontSize: isInResponsiveMode ? 'lg' : 'sm', lineHeight: "relaxed", letterSpacing: "wide", fontWeight: "bold" }, item.title));
3568
3589
  });
3569
3590
  Divider.displayName = 'Divider';
3591
+ const TOCContainer = React__namespace.memo(({ children, updatedTree }) => {
3592
+ const { setLastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3593
+ React__namespace.useEffect(() => {
3594
+ const firstNode = findFirstNode(updatedTree);
3595
+ if (firstNode) {
3596
+ setLastActiveIndex(firstNode.index);
3597
+ }
3598
+ }, []);
3599
+ return React__namespace.createElement(mosaic.Box, null, children);
3600
+ });
3601
+ TOCContainer.displayName = 'TOCContainer';
3570
3602
  const GroupItem = React__namespace.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3571
3603
  if (isExternalLink(item)) {
3572
3604
  return (React__namespace.createElement(mosaic.Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3584,9 +3616,24 @@ const GroupItem = React__namespace.memo(({ item, depth, maxDepthOpenByDefault, i
3584
3616
  });
3585
3617
  GroupItem.displayName = 'GroupItem';
3586
3618
  const Group = React__namespace.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3587
- const activeId = React__namespace.useContext(ActiveIdContext);
3619
+ const { activeId, lastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3588
3620
  const [isOpen, setIsOpen] = React__namespace.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3589
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3621
+ const isActiveGroup = React__namespace.useCallback((items, activeId, contextIndex) => {
3622
+ return items.some(element => {
3623
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3624
+ const hasItems = 'items' in element && Array.isArray(element.items);
3625
+ if (!hasSlugOrId && !hasItems)
3626
+ return false;
3627
+ if (activeId &&
3628
+ 'index' in element &&
3629
+ (element.slug === activeId || element.id === activeId) &&
3630
+ element.index === contextIndex) {
3631
+ return true;
3632
+ }
3633
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3634
+ });
3635
+ }, []);
3636
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3590
3637
  React__namespace.useEffect(() => {
3591
3638
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3592
3639
  if (isOpen !== openByDefault) {
@@ -3636,8 +3683,10 @@ const Item = React__namespace.memo(({ depth, isActive, id, title, meta, icon, is
3636
3683
  });
3637
3684
  Item.displayName = 'Item';
3638
3685
  const Node = React__namespace.memo(({ item, depth, meta, showAsActive, isInResponsiveMode, onClick, onLinkClick = () => { } }) => {
3639
- const activeId = React__namespace.useContext(ActiveIdContext);
3640
- const isActive = activeId === item.slug || activeId === item.id;
3686
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3687
+ const { index } = item;
3688
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3689
+ const isActive = lastActiveIndex === index && isSlugMatched;
3641
3690
  const LinkComponent = React__namespace.useContext(LinkContext);
3642
3691
  const handleClick = (e) => {
3643
3692
  if (isActive) {
@@ -3645,6 +3694,7 @@ const Node = React__namespace.memo(({ item, depth, meta, showAsActive, isInRespo
3645
3694
  e.preventDefault();
3646
3695
  }
3647
3696
  else {
3697
+ setLastActiveIndex(index);
3648
3698
  onLinkClick();
3649
3699
  }
3650
3700
  if (onClick) {
@@ -3652,7 +3702,7 @@ const Node = React__namespace.memo(({ item, depth, meta, showAsActive, isInRespo
3652
3702
  }
3653
3703
  };
3654
3704
  return (React__namespace.createElement(mosaic.Box, { as: LinkComponent, to: resolveRelativeLink(item.slug), display: "block", textDecoration: "no-underline", className: "ElementsTableOfContentsItem" },
3655
- React__namespace.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React__namespace.createElement(mosaic.Box, { as: mosaic.Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: handleClick })));
3705
+ React__namespace.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React__namespace.createElement(mosaic.Box, { as: mosaic.Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: e => handleClick(e) })));
3656
3706
  });
3657
3707
  Node.displayName = 'Node';
3658
3708
  const Version = ({ value }) => {
package/index.mjs CHANGED
@@ -3496,7 +3496,7 @@ function findFirstNode(items) {
3496
3496
  return;
3497
3497
  }
3498
3498
  function isDivider(item) {
3499
- return Object.keys(item).length === 1 && 'title' in item;
3499
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3500
3500
  }
3501
3501
  function isGroup(item) {
3502
3502
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3508,13 +3508,33 @@ function isNode(item) {
3508
3508
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3509
3509
  }
3510
3510
  function isExternalLink(item) {
3511
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3511
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3512
3512
  }
3513
3513
 
3514
- const ActiveIdContext = React.createContext(undefined);
3514
+ const ActiveItemContext = React.createContext({
3515
+ activeId: undefined,
3516
+ lastActiveIndex: '',
3517
+ setLastActiveIndex: () => { },
3518
+ });
3515
3519
  const LinkContext = React.createContext(undefined);
3516
3520
  LinkContext.displayName = 'LinkContext';
3517
3521
  const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3522
+ const [lastActiveIndex, setLastActiveIndex] = useState('');
3523
+ const value = React.useMemo(() => ({
3524
+ lastActiveIndex,
3525
+ setLastActiveIndex,
3526
+ activeId,
3527
+ }), [lastActiveIndex, activeId]);
3528
+ const updateTocTree = React.useCallback((arr, parentId) => {
3529
+ return arr.map((item, key) => {
3530
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3531
+ if (isGroup(item) || isNodeGroup(item)) {
3532
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3533
+ }
3534
+ return newItem;
3535
+ });
3536
+ }, []);
3537
+ const updatedTree = updateTocTree(tree, '');
3518
3538
  const container = React.useRef(null);
3519
3539
  const child = React.useRef(null);
3520
3540
  const firstRender = useFirstRender();
@@ -3534,18 +3554,30 @@ const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefaul
3534
3554
  return (React.createElement(Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3535
3555
  React.createElement(Box, { ref: child, my: 3 },
3536
3556
  React.createElement(LinkContext.Provider, { value: Link },
3537
- React.createElement(ActiveIdContext.Provider, { value: activeId }, tree.map((item, key) => {
3538
- if (isDivider(item)) {
3539
- return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3540
- }
3541
- return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3542
- }))))));
3557
+ React.createElement(ActiveItemContext.Provider, { value: value },
3558
+ React.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3559
+ if (isDivider(item)) {
3560
+ return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3561
+ }
3562
+ return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3563
+ })))))));
3543
3564
  });
3544
3565
  TableOfContents.displayName = 'TableOfContents';
3545
3566
  const Divider = React.memo(({ item, isInResponsiveMode = false }) => {
3546
3567
  return (React.createElement(Box, { pl: 4, mb: 2, mt: 6, textTransform: "uppercase", fontSize: isInResponsiveMode ? 'lg' : 'sm', lineHeight: "relaxed", letterSpacing: "wide", fontWeight: "bold" }, item.title));
3547
3568
  });
3548
3569
  Divider.displayName = 'Divider';
3570
+ const TOCContainer = React.memo(({ children, updatedTree }) => {
3571
+ const { setLastActiveIndex } = React.useContext(ActiveItemContext);
3572
+ React.useEffect(() => {
3573
+ const firstNode = findFirstNode(updatedTree);
3574
+ if (firstNode) {
3575
+ setLastActiveIndex(firstNode.index);
3576
+ }
3577
+ }, []);
3578
+ return React.createElement(Box, null, children);
3579
+ });
3580
+ TOCContainer.displayName = 'TOCContainer';
3549
3581
  const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3550
3582
  if (isExternalLink(item)) {
3551
3583
  return (React.createElement(Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3563,9 +3595,24 @@ const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsi
3563
3595
  });
3564
3596
  GroupItem.displayName = 'GroupItem';
3565
3597
  const Group = React.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3566
- const activeId = React.useContext(ActiveIdContext);
3598
+ const { activeId, lastActiveIndex } = React.useContext(ActiveItemContext);
3567
3599
  const [isOpen, setIsOpen] = React.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3568
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3600
+ const isActiveGroup = React.useCallback((items, activeId, contextIndex) => {
3601
+ return items.some(element => {
3602
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3603
+ const hasItems = 'items' in element && Array.isArray(element.items);
3604
+ if (!hasSlugOrId && !hasItems)
3605
+ return false;
3606
+ if (activeId &&
3607
+ 'index' in element &&
3608
+ (element.slug === activeId || element.id === activeId) &&
3609
+ element.index === contextIndex) {
3610
+ return true;
3611
+ }
3612
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3613
+ });
3614
+ }, []);
3615
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3569
3616
  React.useEffect(() => {
3570
3617
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3571
3618
  if (isOpen !== openByDefault) {
@@ -3615,8 +3662,10 @@ const Item = React.memo(({ depth, isActive, id, title, meta, icon, isInResponsiv
3615
3662
  });
3616
3663
  Item.displayName = 'Item';
3617
3664
  const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode, onClick, onLinkClick = () => { } }) => {
3618
- const activeId = React.useContext(ActiveIdContext);
3619
- const isActive = activeId === item.slug || activeId === item.id;
3665
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React.useContext(ActiveItemContext);
3666
+ const { index } = item;
3667
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3668
+ const isActive = lastActiveIndex === index && isSlugMatched;
3620
3669
  const LinkComponent = React.useContext(LinkContext);
3621
3670
  const handleClick = (e) => {
3622
3671
  if (isActive) {
@@ -3624,6 +3673,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3624
3673
  e.preventDefault();
3625
3674
  }
3626
3675
  else {
3676
+ setLastActiveIndex(index);
3627
3677
  onLinkClick();
3628
3678
  }
3629
3679
  if (onClick) {
@@ -3631,7 +3681,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3631
3681
  }
3632
3682
  };
3633
3683
  return (React.createElement(Box, { as: LinkComponent, to: resolveRelativeLink(item.slug), display: "block", textDecoration: "no-underline", className: "ElementsTableOfContentsItem" },
3634
- React.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React.createElement(Box, { as: Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: handleClick })));
3684
+ React.createElement(Item, { id: getHtmlIdFromItemId(item.slug || item.id), isActive: isActive || showAsActive, depth: depth, title: item.title, icon: NODE_TYPE_TITLE_ICON[item.type] && (React.createElement(Box, { as: Icon, color: NODE_TYPE_ICON_COLOR[item.type], icon: NODE_TYPE_TITLE_ICON[item.type] })), meta: meta, isInResponsiveMode: isInResponsiveMode, onClick: e => handleClick(e) })));
3635
3685
  });
3636
3686
  Node.displayName = 'Node';
3637
3687
  const Version = ({ value }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "9.0.12",
3
+ "version": "9.0.13",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",