@stoplight/elements-core 9.0.12 → 9.0.13-alpha-0.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.
@@ -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
+ };
@@ -4,12 +4,12 @@ import { JSONSchema7, JSONSchema7Definition } from 'json-schema';
4
4
  export declare type ParameterSpec = Pick<IHttpParam, 'name' | 'schema' | 'required'> & {
5
5
  examples?: (Omit<INodeExample, 'id'> | Omit<INodeExternalExample, 'id'>)[];
6
6
  };
7
- export declare function parameterOptions(parameter: ParameterSpec): ({
7
+ export declare function encodeSafeSelectorValue(value: string | number): string | number;
8
+ export declare function decodeSafeSelectorValue(value: string | number): string | number;
9
+ export declare function parameterOptions(parameter: ParameterSpec): {
8
10
  value: string | number;
9
- } | {
10
11
  label: string;
11
- value: string;
12
- })[] | null;
12
+ }[] | null;
13
13
  export declare const selectExampleOption: {
14
14
  value: string;
15
15
  label: string;
package/index.esm.js CHANGED
@@ -1340,8 +1340,50 @@ const booleanOptions = [
1340
1340
  { label: 'False', value: 'false' },
1341
1341
  { label: 'True', value: 'true' },
1342
1342
  ];
1343
+ function encodeSafeSelectorValue(value) {
1344
+ if (typeof value === 'number') {
1345
+ return value;
1346
+ }
1347
+ const hasSpecialChars = /["'\[\]\\(){}]/.test(value);
1348
+ if (!hasSpecialChars) {
1349
+ return value;
1350
+ }
1351
+ try {
1352
+ return 'b64:' + btoa(value);
1353
+ }
1354
+ catch (e) {
1355
+ return 'enc:' + encodeURIComponent(value);
1356
+ }
1357
+ }
1358
+ function decodeSafeSelectorValue(value) {
1359
+ if (typeof value === 'number') {
1360
+ return value;
1361
+ }
1362
+ if (value.startsWith('b64:')) {
1363
+ try {
1364
+ return atob(value.substring(4));
1365
+ }
1366
+ catch (e) {
1367
+ return value;
1368
+ }
1369
+ }
1370
+ if (value.startsWith('enc:')) {
1371
+ try {
1372
+ return decodeURIComponent(value.substring(4));
1373
+ }
1374
+ catch (e) {
1375
+ return value;
1376
+ }
1377
+ }
1378
+ return value;
1379
+ }
1343
1380
  function enumOptions(enumValues, required) {
1344
- const options = map(enumValues, v => ({ value: typeof v === 'number' ? v : String(v) }));
1381
+ const options = map(enumValues, v => {
1382
+ var _a;
1383
+ const stringValue = typeof v === 'object' && v !== null ? (_a = safeStringify(v)) !== null && _a !== void 0 ? _a : String(v) : typeof v === 'number' ? v : String(v);
1384
+ const safeValue = encodeSafeSelectorValue(stringValue);
1385
+ return { value: safeValue, label: String(stringValue) };
1386
+ });
1345
1387
  return required ? options : [{ label: 'Not Set', value: '' }, ...options];
1346
1388
  }
1347
1389
  function parameterOptions(parameter) {
@@ -1371,15 +1413,16 @@ function parameterSupportsFileUpload(parameter) {
1371
1413
  ((_c = parameter.schema) === null || _c === void 0 ? void 0 : _c.contentMediaType) === 'application/octet-stream'));
1372
1414
  }
1373
1415
  function stringifyValue(value) {
1374
- return typeof value === 'object' ? JSON.stringify(value) : escapeQuotes(String(value));
1416
+ var _a;
1417
+ if (typeof value === 'object' && value !== null) {
1418
+ return (_a = safeStringify(value)) !== null && _a !== void 0 ? _a : String(value);
1419
+ }
1420
+ return String(value);
1375
1421
  }
1376
1422
  function exampleValue(example) {
1377
1423
  const value = 'value' in example ? example.value : example.externalValue;
1378
1424
  return stringifyValue(value);
1379
1425
  }
1380
- function escapeQuotes(value) {
1381
- return value.replace(/"/g, '\\"');
1382
- }
1383
1426
  function getPlaceholderForParameter(parameter) {
1384
1427
  var _a, _b;
1385
1428
  const { value: parameterValue, isDefault } = getValueForParameter(parameter);
@@ -1405,14 +1448,14 @@ const getValueForParameter = (parameter) => {
1405
1448
  if (typeof defaultValue !== 'undefined') {
1406
1449
  return { value: stringifyValue(defaultValue), isDefault: true };
1407
1450
  }
1408
- const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1409
- if (examples.length > 0) {
1410
- return { value: exampleValue(examples[0]) };
1411
- }
1412
- const enums = (_c = (_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.enum) !== null && _c !== void 0 ? _c : [];
1451
+ const enums = (_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.enum) !== null && _b !== void 0 ? _b : [];
1413
1452
  if (enums.length > 0) {
1414
1453
  return { value: stringifyValue(enums[0]) };
1415
1454
  }
1455
+ const examples = (_c = parameter.examples) !== null && _c !== void 0 ? _c : [];
1456
+ if (examples.length > 0) {
1457
+ return { value: exampleValue(examples[0]) };
1458
+ }
1416
1459
  return { value: '' };
1417
1460
  };
1418
1461
  const getInitialValueForParameter = (parameter) => {
@@ -1468,11 +1511,20 @@ const ParameterEditor = ({ parameter, value, onChange, isOptional, onChangeOptio
1468
1511
  const examples = exampleOptions(parameter);
1469
1512
  const selectedExample = (_a = examples === null || examples === void 0 ? void 0 : examples.find(e => e.value === value)) !== null && _a !== void 0 ? _a : selectExampleOption;
1470
1513
  const parameterDisplayName = `${parameter.name}${parameter.required ? '*' : ''}`;
1514
+ console.log("Inside Parameter Editor in APLHA BRANCH");
1515
+ const encodedValue = React.useMemo(() => {
1516
+ if (!value || !parameterValueOptions)
1517
+ return value || '';
1518
+ const matchingOption = parameterValueOptions.find(opt => {
1519
+ return String(decodeSafeSelectorValue(opt.value)) === value;
1520
+ });
1521
+ return matchingOption ? String(matchingOption.value) : value;
1522
+ }, [value, parameterValueOptions]);
1471
1523
  const requiredButEmpty = validate && parameter.required && !value;
1472
1524
  return (React.createElement(React.Fragment, null,
1473
1525
  React.createElement(Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, parameterDisplayName),
1474
1526
  React.createElement(Text, { mx: 3 }, ":"),
1475
- React.createElement("div", null, parameterValueOptions ? (React.createElement(Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: value || '', onChange: onChange, placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React.createElement(Flex, { flex: 1 },
1527
+ React.createElement("div", null, parameterValueOptions ? (React.createElement(Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: encodedValue, onChange: val => onChange && onChange(String(decodeSafeSelectorValue(val))), placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React.createElement(Flex, { flex: 1 },
1476
1528
  React.createElement(Input, { id: inputId, "aria-label": parameter.name, appearance: requiredButEmpty ? 'default' : 'minimal', flex: 1, placeholder: getPlaceholderForParameter(parameter), type: ((_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.type) === 'number' ? 'number' : 'text', required: true, intent: requiredButEmpty ? 'danger' : 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }),
1477
1529
  examples && (React.createElement(Select, { "aria-label": `${parameter.name}-select`, flex: 1, value: selectedExample.value, options: examples, onChange: onChange }))))),
1478
1530
  canChangeOptional && !parameter.required && (React.createElement(React.Fragment, null,
@@ -2327,10 +2379,17 @@ ServersDropdown.displayName = 'ServersDropdown';
2327
2379
 
2328
2380
  const VariableEditor = ({ variable, value, onChange }) => {
2329
2381
  const inputId = useUniqueId(`id_${variable.name}_`);
2382
+ const encodedOptions = React.useMemo(() => (variable.enum ? variable.enum.map(s => ({ value: encodeSafeSelectorValue(s), label: String(s) })) : []), [variable.enum]);
2383
+ const encodedValue = React.useMemo(() => {
2384
+ if (!value || !variable.enum)
2385
+ return value || variable.default;
2386
+ const matchingOption = encodedOptions.find(opt => decodeSafeSelectorValue(String(opt.value)) === value);
2387
+ return matchingOption ? String(matchingOption.value) : value;
2388
+ }, [value, variable.enum, variable.default, encodedOptions]);
2330
2389
  return (React.createElement(React.Fragment, null,
2331
2390
  React.createElement(Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, variable.name),
2332
2391
  React.createElement(Text, { mx: 3 }, ":"),
2333
- React.createElement("div", null, variable.enum ? (React.createElement(Select, { flex: 1, "aria-label": variable.name, options: variable.enum.map(s => ({ value: s })), value: value || variable.default, onChange: onChange })) : (React.createElement(Flex, { flex: 1 },
2392
+ React.createElement("div", null, variable.enum ? (React.createElement(Select, { flex: 1, "aria-label": variable.name, options: encodedOptions, value: encodedValue, onChange: val => onChange && onChange(decodeSafeSelectorValue(String(val))) })) : (React.createElement(Flex, { flex: 1 },
2334
2393
  React.createElement(Input, { id: inputId, "aria-label": variable.name, appearance: 'minimal', flex: 1, placeholder: variable.default, type: "text", required: true, intent: 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }))))));
2335
2394
  };
2336
2395
 
@@ -3496,7 +3555,7 @@ function findFirstNode(items) {
3496
3555
  return;
3497
3556
  }
3498
3557
  function isDivider(item) {
3499
- return Object.keys(item).length === 1 && 'title' in item;
3558
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3500
3559
  }
3501
3560
  function isGroup(item) {
3502
3561
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3508,13 +3567,33 @@ function isNode(item) {
3508
3567
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3509
3568
  }
3510
3569
  function isExternalLink(item) {
3511
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3570
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3512
3571
  }
3513
3572
 
3514
- const ActiveIdContext = React.createContext(undefined);
3573
+ const ActiveItemContext = React.createContext({
3574
+ activeId: undefined,
3575
+ lastActiveIndex: '',
3576
+ setLastActiveIndex: () => { },
3577
+ });
3515
3578
  const LinkContext = React.createContext(undefined);
3516
3579
  LinkContext.displayName = 'LinkContext';
3517
3580
  const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3581
+ const [lastActiveIndex, setLastActiveIndex] = useState('');
3582
+ const value = React.useMemo(() => ({
3583
+ lastActiveIndex,
3584
+ setLastActiveIndex,
3585
+ activeId,
3586
+ }), [lastActiveIndex, activeId]);
3587
+ const updateTocTree = React.useCallback((arr, parentId) => {
3588
+ return arr.map((item, key) => {
3589
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3590
+ if (isGroup(item) || isNodeGroup(item)) {
3591
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3592
+ }
3593
+ return newItem;
3594
+ });
3595
+ }, []);
3596
+ const updatedTree = updateTocTree(tree, '');
3518
3597
  const container = React.useRef(null);
3519
3598
  const child = React.useRef(null);
3520
3599
  const firstRender = useFirstRender();
@@ -3534,18 +3613,30 @@ const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefaul
3534
3613
  return (React.createElement(Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3535
3614
  React.createElement(Box, { ref: child, my: 3 },
3536
3615
  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
- }))))));
3616
+ React.createElement(ActiveItemContext.Provider, { value: value },
3617
+ React.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3618
+ if (isDivider(item)) {
3619
+ return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3620
+ }
3621
+ return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3622
+ })))))));
3543
3623
  });
3544
3624
  TableOfContents.displayName = 'TableOfContents';
3545
3625
  const Divider = React.memo(({ item, isInResponsiveMode = false }) => {
3546
3626
  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
3627
  });
3548
3628
  Divider.displayName = 'Divider';
3629
+ const TOCContainer = React.memo(({ children, updatedTree }) => {
3630
+ const { setLastActiveIndex } = React.useContext(ActiveItemContext);
3631
+ React.useEffect(() => {
3632
+ const firstNode = findFirstNode(updatedTree);
3633
+ if (firstNode) {
3634
+ setLastActiveIndex(firstNode.index);
3635
+ }
3636
+ }, []);
3637
+ return React.createElement(Box, null, children);
3638
+ });
3639
+ TOCContainer.displayName = 'TOCContainer';
3549
3640
  const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3550
3641
  if (isExternalLink(item)) {
3551
3642
  return (React.createElement(Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3563,9 +3654,24 @@ const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsi
3563
3654
  });
3564
3655
  GroupItem.displayName = 'GroupItem';
3565
3656
  const Group = React.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3566
- const activeId = React.useContext(ActiveIdContext);
3657
+ const { activeId, lastActiveIndex } = React.useContext(ActiveItemContext);
3567
3658
  const [isOpen, setIsOpen] = React.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3568
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3659
+ const isActiveGroup = React.useCallback((items, activeId, contextIndex) => {
3660
+ return items.some(element => {
3661
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3662
+ const hasItems = 'items' in element && Array.isArray(element.items);
3663
+ if (!hasSlugOrId && !hasItems)
3664
+ return false;
3665
+ if (activeId &&
3666
+ 'index' in element &&
3667
+ (element.slug === activeId || element.id === activeId) &&
3668
+ element.index === contextIndex) {
3669
+ return true;
3670
+ }
3671
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3672
+ });
3673
+ }, []);
3674
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3569
3675
  React.useEffect(() => {
3570
3676
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3571
3677
  if (isOpen !== openByDefault) {
@@ -3615,8 +3721,10 @@ const Item = React.memo(({ depth, isActive, id, title, meta, icon, isInResponsiv
3615
3721
  });
3616
3722
  Item.displayName = 'Item';
3617
3723
  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;
3724
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React.useContext(ActiveItemContext);
3725
+ const { index } = item;
3726
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3727
+ const isActive = lastActiveIndex === index && isSlugMatched;
3620
3728
  const LinkComponent = React.useContext(LinkContext);
3621
3729
  const handleClick = (e) => {
3622
3730
  if (isActive) {
@@ -3624,6 +3732,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3624
3732
  e.preventDefault();
3625
3733
  }
3626
3734
  else {
3735
+ setLastActiveIndex(index);
3627
3736
  onLinkClick();
3628
3737
  }
3629
3738
  if (onClick) {
@@ -3631,7 +3740,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3631
3740
  }
3632
3741
  };
3633
3742
  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 })));
3743
+ 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
3744
  });
3636
3745
  Node.displayName = 'Node';
3637
3746
  const Version = ({ value }) => {
package/index.js CHANGED
@@ -1361,8 +1361,50 @@ const booleanOptions = [
1361
1361
  { label: 'False', value: 'false' },
1362
1362
  { label: 'True', value: 'true' },
1363
1363
  ];
1364
+ function encodeSafeSelectorValue(value) {
1365
+ if (typeof value === 'number') {
1366
+ return value;
1367
+ }
1368
+ const hasSpecialChars = /["'\[\]\\(){}]/.test(value);
1369
+ if (!hasSpecialChars) {
1370
+ return value;
1371
+ }
1372
+ try {
1373
+ return 'b64:' + btoa(value);
1374
+ }
1375
+ catch (e) {
1376
+ return 'enc:' + encodeURIComponent(value);
1377
+ }
1378
+ }
1379
+ function decodeSafeSelectorValue(value) {
1380
+ if (typeof value === 'number') {
1381
+ return value;
1382
+ }
1383
+ if (value.startsWith('b64:')) {
1384
+ try {
1385
+ return atob(value.substring(4));
1386
+ }
1387
+ catch (e) {
1388
+ return value;
1389
+ }
1390
+ }
1391
+ if (value.startsWith('enc:')) {
1392
+ try {
1393
+ return decodeURIComponent(value.substring(4));
1394
+ }
1395
+ catch (e) {
1396
+ return value;
1397
+ }
1398
+ }
1399
+ return value;
1400
+ }
1364
1401
  function enumOptions(enumValues, required) {
1365
- const options = map(enumValues, v => ({ value: typeof v === 'number' ? v : String(v) }));
1402
+ const options = map(enumValues, v => {
1403
+ var _a;
1404
+ const stringValue = typeof v === 'object' && v !== null ? (_a = json.safeStringify(v)) !== null && _a !== void 0 ? _a : String(v) : typeof v === 'number' ? v : String(v);
1405
+ const safeValue = encodeSafeSelectorValue(stringValue);
1406
+ return { value: safeValue, label: String(stringValue) };
1407
+ });
1366
1408
  return required ? options : [{ label: 'Not Set', value: '' }, ...options];
1367
1409
  }
1368
1410
  function parameterOptions(parameter) {
@@ -1392,15 +1434,16 @@ function parameterSupportsFileUpload(parameter) {
1392
1434
  ((_c = parameter.schema) === null || _c === void 0 ? void 0 : _c.contentMediaType) === 'application/octet-stream'));
1393
1435
  }
1394
1436
  function stringifyValue(value) {
1395
- return typeof value === 'object' ? JSON.stringify(value) : escapeQuotes(String(value));
1437
+ var _a;
1438
+ if (typeof value === 'object' && value !== null) {
1439
+ return (_a = json.safeStringify(value)) !== null && _a !== void 0 ? _a : String(value);
1440
+ }
1441
+ return String(value);
1396
1442
  }
1397
1443
  function exampleValue(example) {
1398
1444
  const value = 'value' in example ? example.value : example.externalValue;
1399
1445
  return stringifyValue(value);
1400
1446
  }
1401
- function escapeQuotes(value) {
1402
- return value.replace(/"/g, '\\"');
1403
- }
1404
1447
  function getPlaceholderForParameter(parameter) {
1405
1448
  var _a, _b;
1406
1449
  const { value: parameterValue, isDefault } = getValueForParameter(parameter);
@@ -1426,14 +1469,14 @@ const getValueForParameter = (parameter) => {
1426
1469
  if (typeof defaultValue !== 'undefined') {
1427
1470
  return { value: stringifyValue(defaultValue), isDefault: true };
1428
1471
  }
1429
- const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1430
- if (examples.length > 0) {
1431
- return { value: exampleValue(examples[0]) };
1432
- }
1433
- const enums = (_c = (_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.enum) !== null && _c !== void 0 ? _c : [];
1472
+ const enums = (_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.enum) !== null && _b !== void 0 ? _b : [];
1434
1473
  if (enums.length > 0) {
1435
1474
  return { value: stringifyValue(enums[0]) };
1436
1475
  }
1476
+ const examples = (_c = parameter.examples) !== null && _c !== void 0 ? _c : [];
1477
+ if (examples.length > 0) {
1478
+ return { value: exampleValue(examples[0]) };
1479
+ }
1437
1480
  return { value: '' };
1438
1481
  };
1439
1482
  const getInitialValueForParameter = (parameter) => {
@@ -1489,11 +1532,20 @@ const ParameterEditor = ({ parameter, value, onChange, isOptional, onChangeOptio
1489
1532
  const examples = exampleOptions(parameter);
1490
1533
  const selectedExample = (_a = examples === null || examples === void 0 ? void 0 : examples.find(e => e.value === value)) !== null && _a !== void 0 ? _a : selectExampleOption;
1491
1534
  const parameterDisplayName = `${parameter.name}${parameter.required ? '*' : ''}`;
1535
+ console.log("Inside Parameter Editor in APLHA BRANCH");
1536
+ const encodedValue = React__namespace.useMemo(() => {
1537
+ if (!value || !parameterValueOptions)
1538
+ return value || '';
1539
+ const matchingOption = parameterValueOptions.find(opt => {
1540
+ return String(decodeSafeSelectorValue(opt.value)) === value;
1541
+ });
1542
+ return matchingOption ? String(matchingOption.value) : value;
1543
+ }, [value, parameterValueOptions]);
1492
1544
  const requiredButEmpty = validate && parameter.required && !value;
1493
1545
  return (React__namespace.createElement(React__namespace.Fragment, null,
1494
1546
  React__namespace.createElement(mosaic.Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, parameterDisplayName),
1495
1547
  React__namespace.createElement(mosaic.Text, { mx: 3 }, ":"),
1496
- React__namespace.createElement("div", null, parameterValueOptions ? (React__namespace.createElement(mosaic.Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: value || '', onChange: onChange, placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React__namespace.createElement(mosaic.Flex, { flex: 1 },
1548
+ React__namespace.createElement("div", null, parameterValueOptions ? (React__namespace.createElement(mosaic.Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: encodedValue, onChange: val => onChange && onChange(String(decodeSafeSelectorValue(val))), placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React__namespace.createElement(mosaic.Flex, { flex: 1 },
1497
1549
  React__namespace.createElement(mosaic.Input, { id: inputId, "aria-label": parameter.name, appearance: requiredButEmpty ? 'default' : 'minimal', flex: 1, placeholder: getPlaceholderForParameter(parameter), type: ((_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.type) === 'number' ? 'number' : 'text', required: true, intent: requiredButEmpty ? 'danger' : 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }),
1498
1550
  examples && (React__namespace.createElement(mosaic.Select, { "aria-label": `${parameter.name}-select`, flex: 1, value: selectedExample.value, options: examples, onChange: onChange }))))),
1499
1551
  canChangeOptional && !parameter.required && (React__namespace.createElement(React__namespace.Fragment, null,
@@ -2348,10 +2400,17 @@ ServersDropdown.displayName = 'ServersDropdown';
2348
2400
 
2349
2401
  const VariableEditor = ({ variable, value, onChange }) => {
2350
2402
  const inputId = useUniqueId(`id_${variable.name}_`);
2403
+ const encodedOptions = React__namespace.useMemo(() => (variable.enum ? variable.enum.map(s => ({ value: encodeSafeSelectorValue(s), label: String(s) })) : []), [variable.enum]);
2404
+ const encodedValue = React__namespace.useMemo(() => {
2405
+ if (!value || !variable.enum)
2406
+ return value || variable.default;
2407
+ const matchingOption = encodedOptions.find(opt => decodeSafeSelectorValue(String(opt.value)) === value);
2408
+ return matchingOption ? String(matchingOption.value) : value;
2409
+ }, [value, variable.enum, variable.default, encodedOptions]);
2351
2410
  return (React__namespace.createElement(React__namespace.Fragment, null,
2352
2411
  React__namespace.createElement(mosaic.Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, variable.name),
2353
2412
  React__namespace.createElement(mosaic.Text, { mx: 3 }, ":"),
2354
- React__namespace.createElement("div", null, variable.enum ? (React__namespace.createElement(mosaic.Select, { flex: 1, "aria-label": variable.name, options: variable.enum.map(s => ({ value: s })), value: value || variable.default, onChange: onChange })) : (React__namespace.createElement(mosaic.Flex, { flex: 1 },
2413
+ React__namespace.createElement("div", null, variable.enum ? (React__namespace.createElement(mosaic.Select, { flex: 1, "aria-label": variable.name, options: encodedOptions, value: encodedValue, onChange: val => onChange && onChange(decodeSafeSelectorValue(String(val))) })) : (React__namespace.createElement(mosaic.Flex, { flex: 1 },
2355
2414
  React__namespace.createElement(mosaic.Input, { id: inputId, "aria-label": variable.name, appearance: 'minimal', flex: 1, placeholder: variable.default, type: "text", required: true, intent: 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }))))));
2356
2415
  };
2357
2416
 
@@ -3517,7 +3576,7 @@ function findFirstNode(items) {
3517
3576
  return;
3518
3577
  }
3519
3578
  function isDivider(item) {
3520
- return Object.keys(item).length === 1 && 'title' in item;
3579
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3521
3580
  }
3522
3581
  function isGroup(item) {
3523
3582
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3529,13 +3588,33 @@ function isNode(item) {
3529
3588
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3530
3589
  }
3531
3590
  function isExternalLink(item) {
3532
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3591
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3533
3592
  }
3534
3593
 
3535
- const ActiveIdContext = React__namespace.createContext(undefined);
3594
+ const ActiveItemContext = React__namespace.createContext({
3595
+ activeId: undefined,
3596
+ lastActiveIndex: '',
3597
+ setLastActiveIndex: () => { },
3598
+ });
3536
3599
  const LinkContext = React__namespace.createContext(undefined);
3537
3600
  LinkContext.displayName = 'LinkContext';
3538
3601
  const TableOfContents = React__namespace.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3602
+ const [lastActiveIndex, setLastActiveIndex] = React.useState('');
3603
+ const value = React__namespace.useMemo(() => ({
3604
+ lastActiveIndex,
3605
+ setLastActiveIndex,
3606
+ activeId,
3607
+ }), [lastActiveIndex, activeId]);
3608
+ const updateTocTree = React__namespace.useCallback((arr, parentId) => {
3609
+ return arr.map((item, key) => {
3610
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3611
+ if (isGroup(item) || isNodeGroup(item)) {
3612
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3613
+ }
3614
+ return newItem;
3615
+ });
3616
+ }, []);
3617
+ const updatedTree = updateTocTree(tree, '');
3539
3618
  const container = React__namespace.useRef(null);
3540
3619
  const child = React__namespace.useRef(null);
3541
3620
  const firstRender = useFirstRender();
@@ -3555,18 +3634,30 @@ const TableOfContents = React__namespace.memo(({ tree, activeId, Link, maxDepthO
3555
3634
  return (React__namespace.createElement(mosaic.Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3556
3635
  React__namespace.createElement(mosaic.Box, { ref: child, my: 3 },
3557
3636
  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
- }))))));
3637
+ React__namespace.createElement(ActiveItemContext.Provider, { value: value },
3638
+ React__namespace.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3639
+ if (isDivider(item)) {
3640
+ return React__namespace.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3641
+ }
3642
+ return (React__namespace.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3643
+ })))))));
3564
3644
  });
3565
3645
  TableOfContents.displayName = 'TableOfContents';
3566
3646
  const Divider = React__namespace.memo(({ item, isInResponsiveMode = false }) => {
3567
3647
  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
3648
  });
3569
3649
  Divider.displayName = 'Divider';
3650
+ const TOCContainer = React__namespace.memo(({ children, updatedTree }) => {
3651
+ const { setLastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3652
+ React__namespace.useEffect(() => {
3653
+ const firstNode = findFirstNode(updatedTree);
3654
+ if (firstNode) {
3655
+ setLastActiveIndex(firstNode.index);
3656
+ }
3657
+ }, []);
3658
+ return React__namespace.createElement(mosaic.Box, null, children);
3659
+ });
3660
+ TOCContainer.displayName = 'TOCContainer';
3570
3661
  const GroupItem = React__namespace.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3571
3662
  if (isExternalLink(item)) {
3572
3663
  return (React__namespace.createElement(mosaic.Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3584,9 +3675,24 @@ const GroupItem = React__namespace.memo(({ item, depth, maxDepthOpenByDefault, i
3584
3675
  });
3585
3676
  GroupItem.displayName = 'GroupItem';
3586
3677
  const Group = React__namespace.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3587
- const activeId = React__namespace.useContext(ActiveIdContext);
3678
+ const { activeId, lastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3588
3679
  const [isOpen, setIsOpen] = React__namespace.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3589
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3680
+ const isActiveGroup = React__namespace.useCallback((items, activeId, contextIndex) => {
3681
+ return items.some(element => {
3682
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3683
+ const hasItems = 'items' in element && Array.isArray(element.items);
3684
+ if (!hasSlugOrId && !hasItems)
3685
+ return false;
3686
+ if (activeId &&
3687
+ 'index' in element &&
3688
+ (element.slug === activeId || element.id === activeId) &&
3689
+ element.index === contextIndex) {
3690
+ return true;
3691
+ }
3692
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3693
+ });
3694
+ }, []);
3695
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3590
3696
  React__namespace.useEffect(() => {
3591
3697
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3592
3698
  if (isOpen !== openByDefault) {
@@ -3636,8 +3742,10 @@ const Item = React__namespace.memo(({ depth, isActive, id, title, meta, icon, is
3636
3742
  });
3637
3743
  Item.displayName = 'Item';
3638
3744
  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;
3745
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React__namespace.useContext(ActiveItemContext);
3746
+ const { index } = item;
3747
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3748
+ const isActive = lastActiveIndex === index && isSlugMatched;
3641
3749
  const LinkComponent = React__namespace.useContext(LinkContext);
3642
3750
  const handleClick = (e) => {
3643
3751
  if (isActive) {
@@ -3645,6 +3753,7 @@ const Node = React__namespace.memo(({ item, depth, meta, showAsActive, isInRespo
3645
3753
  e.preventDefault();
3646
3754
  }
3647
3755
  else {
3756
+ setLastActiveIndex(index);
3648
3757
  onLinkClick();
3649
3758
  }
3650
3759
  if (onClick) {
@@ -3652,7 +3761,7 @@ const Node = React__namespace.memo(({ item, depth, meta, showAsActive, isInRespo
3652
3761
  }
3653
3762
  };
3654
3763
  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 })));
3764
+ 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
3765
  });
3657
3766
  Node.displayName = 'Node';
3658
3767
  const Version = ({ value }) => {
package/index.mjs CHANGED
@@ -1340,8 +1340,50 @@ const booleanOptions = [
1340
1340
  { label: 'False', value: 'false' },
1341
1341
  { label: 'True', value: 'true' },
1342
1342
  ];
1343
+ function encodeSafeSelectorValue(value) {
1344
+ if (typeof value === 'number') {
1345
+ return value;
1346
+ }
1347
+ const hasSpecialChars = /["'\[\]\\(){}]/.test(value);
1348
+ if (!hasSpecialChars) {
1349
+ return value;
1350
+ }
1351
+ try {
1352
+ return 'b64:' + btoa(value);
1353
+ }
1354
+ catch (e) {
1355
+ return 'enc:' + encodeURIComponent(value);
1356
+ }
1357
+ }
1358
+ function decodeSafeSelectorValue(value) {
1359
+ if (typeof value === 'number') {
1360
+ return value;
1361
+ }
1362
+ if (value.startsWith('b64:')) {
1363
+ try {
1364
+ return atob(value.substring(4));
1365
+ }
1366
+ catch (e) {
1367
+ return value;
1368
+ }
1369
+ }
1370
+ if (value.startsWith('enc:')) {
1371
+ try {
1372
+ return decodeURIComponent(value.substring(4));
1373
+ }
1374
+ catch (e) {
1375
+ return value;
1376
+ }
1377
+ }
1378
+ return value;
1379
+ }
1343
1380
  function enumOptions(enumValues, required) {
1344
- const options = map(enumValues, v => ({ value: typeof v === 'number' ? v : String(v) }));
1381
+ const options = map(enumValues, v => {
1382
+ var _a;
1383
+ const stringValue = typeof v === 'object' && v !== null ? (_a = safeStringify(v)) !== null && _a !== void 0 ? _a : String(v) : typeof v === 'number' ? v : String(v);
1384
+ const safeValue = encodeSafeSelectorValue(stringValue);
1385
+ return { value: safeValue, label: String(stringValue) };
1386
+ });
1345
1387
  return required ? options : [{ label: 'Not Set', value: '' }, ...options];
1346
1388
  }
1347
1389
  function parameterOptions(parameter) {
@@ -1371,15 +1413,16 @@ function parameterSupportsFileUpload(parameter) {
1371
1413
  ((_c = parameter.schema) === null || _c === void 0 ? void 0 : _c.contentMediaType) === 'application/octet-stream'));
1372
1414
  }
1373
1415
  function stringifyValue(value) {
1374
- return typeof value === 'object' ? JSON.stringify(value) : escapeQuotes(String(value));
1416
+ var _a;
1417
+ if (typeof value === 'object' && value !== null) {
1418
+ return (_a = safeStringify(value)) !== null && _a !== void 0 ? _a : String(value);
1419
+ }
1420
+ return String(value);
1375
1421
  }
1376
1422
  function exampleValue(example) {
1377
1423
  const value = 'value' in example ? example.value : example.externalValue;
1378
1424
  return stringifyValue(value);
1379
1425
  }
1380
- function escapeQuotes(value) {
1381
- return value.replace(/"/g, '\\"');
1382
- }
1383
1426
  function getPlaceholderForParameter(parameter) {
1384
1427
  var _a, _b;
1385
1428
  const { value: parameterValue, isDefault } = getValueForParameter(parameter);
@@ -1405,14 +1448,14 @@ const getValueForParameter = (parameter) => {
1405
1448
  if (typeof defaultValue !== 'undefined') {
1406
1449
  return { value: stringifyValue(defaultValue), isDefault: true };
1407
1450
  }
1408
- const examples = (_a = parameter.examples) !== null && _a !== void 0 ? _a : [];
1409
- if (examples.length > 0) {
1410
- return { value: exampleValue(examples[0]) };
1411
- }
1412
- const enums = (_c = (_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.enum) !== null && _c !== void 0 ? _c : [];
1451
+ const enums = (_b = (_a = parameter.schema) === null || _a === void 0 ? void 0 : _a.enum) !== null && _b !== void 0 ? _b : [];
1413
1452
  if (enums.length > 0) {
1414
1453
  return { value: stringifyValue(enums[0]) };
1415
1454
  }
1455
+ const examples = (_c = parameter.examples) !== null && _c !== void 0 ? _c : [];
1456
+ if (examples.length > 0) {
1457
+ return { value: exampleValue(examples[0]) };
1458
+ }
1416
1459
  return { value: '' };
1417
1460
  };
1418
1461
  const getInitialValueForParameter = (parameter) => {
@@ -1468,11 +1511,20 @@ const ParameterEditor = ({ parameter, value, onChange, isOptional, onChangeOptio
1468
1511
  const examples = exampleOptions(parameter);
1469
1512
  const selectedExample = (_a = examples === null || examples === void 0 ? void 0 : examples.find(e => e.value === value)) !== null && _a !== void 0 ? _a : selectExampleOption;
1470
1513
  const parameterDisplayName = `${parameter.name}${parameter.required ? '*' : ''}`;
1514
+ console.log("Inside Parameter Editor in APLHA BRANCH");
1515
+ const encodedValue = React.useMemo(() => {
1516
+ if (!value || !parameterValueOptions)
1517
+ return value || '';
1518
+ const matchingOption = parameterValueOptions.find(opt => {
1519
+ return String(decodeSafeSelectorValue(opt.value)) === value;
1520
+ });
1521
+ return matchingOption ? String(matchingOption.value) : value;
1522
+ }, [value, parameterValueOptions]);
1471
1523
  const requiredButEmpty = validate && parameter.required && !value;
1472
1524
  return (React.createElement(React.Fragment, null,
1473
1525
  React.createElement(Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, parameterDisplayName),
1474
1526
  React.createElement(Text, { mx: 3 }, ":"),
1475
- React.createElement("div", null, parameterValueOptions ? (React.createElement(Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: value || '', onChange: onChange, placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React.createElement(Flex, { flex: 1 },
1527
+ React.createElement("div", null, parameterValueOptions ? (React.createElement(Select, { flex: 1, "aria-label": parameter.name, options: parameterValueOptions, value: encodedValue, onChange: val => onChange && onChange(String(decodeSafeSelectorValue(val))), placeholder: getPlaceholderForSelectedParameter(parameter) })) : (React.createElement(Flex, { flex: 1 },
1476
1528
  React.createElement(Input, { id: inputId, "aria-label": parameter.name, appearance: requiredButEmpty ? 'default' : 'minimal', flex: 1, placeholder: getPlaceholderForParameter(parameter), type: ((_b = parameter.schema) === null || _b === void 0 ? void 0 : _b.type) === 'number' ? 'number' : 'text', required: true, intent: requiredButEmpty ? 'danger' : 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }),
1477
1529
  examples && (React.createElement(Select, { "aria-label": `${parameter.name}-select`, flex: 1, value: selectedExample.value, options: examples, onChange: onChange }))))),
1478
1530
  canChangeOptional && !parameter.required && (React.createElement(React.Fragment, null,
@@ -2327,10 +2379,17 @@ ServersDropdown.displayName = 'ServersDropdown';
2327
2379
 
2328
2380
  const VariableEditor = ({ variable, value, onChange }) => {
2329
2381
  const inputId = useUniqueId(`id_${variable.name}_`);
2382
+ const encodedOptions = React.useMemo(() => (variable.enum ? variable.enum.map(s => ({ value: encodeSafeSelectorValue(s), label: String(s) })) : []), [variable.enum]);
2383
+ const encodedValue = React.useMemo(() => {
2384
+ if (!value || !variable.enum)
2385
+ return value || variable.default;
2386
+ const matchingOption = encodedOptions.find(opt => decodeSafeSelectorValue(String(opt.value)) === value);
2387
+ return matchingOption ? String(matchingOption.value) : value;
2388
+ }, [value, variable.enum, variable.default, encodedOptions]);
2330
2389
  return (React.createElement(React.Fragment, null,
2331
2390
  React.createElement(Text, { as: "label", "aria-hidden": "true", "data-testid": "param-label", htmlFor: inputId, fontSize: "base" }, variable.name),
2332
2391
  React.createElement(Text, { mx: 3 }, ":"),
2333
- React.createElement("div", null, variable.enum ? (React.createElement(Select, { flex: 1, "aria-label": variable.name, options: variable.enum.map(s => ({ value: s })), value: value || variable.default, onChange: onChange })) : (React.createElement(Flex, { flex: 1 },
2392
+ React.createElement("div", null, variable.enum ? (React.createElement(Select, { flex: 1, "aria-label": variable.name, options: encodedOptions, value: encodedValue, onChange: val => onChange && onChange(decodeSafeSelectorValue(String(val))) })) : (React.createElement(Flex, { flex: 1 },
2334
2393
  React.createElement(Input, { id: inputId, "aria-label": variable.name, appearance: 'minimal', flex: 1, placeholder: variable.default, type: "text", required: true, intent: 'default', value: value || '', onChange: e => onChange && onChange(e.currentTarget.value) }))))));
2335
2394
  };
2336
2395
 
@@ -3496,7 +3555,7 @@ function findFirstNode(items) {
3496
3555
  return;
3497
3556
  }
3498
3557
  function isDivider(item) {
3499
- return Object.keys(item).length === 1 && 'title' in item;
3558
+ return Object.keys(item).length === 2 && 'title' in item && 'index' in item;
3500
3559
  }
3501
3560
  function isGroup(item) {
3502
3561
  return Object.keys(item).length >= 2 && 'title' in item && 'items' in item;
@@ -3508,13 +3567,33 @@ function isNode(item) {
3508
3567
  return 'title' in item && 'slug' in item && 'id' in item && 'meta' in item && 'type' in item;
3509
3568
  }
3510
3569
  function isExternalLink(item) {
3511
- return Object.keys(item).length === 2 && 'title' in item && 'url' in item;
3570
+ return Object.keys(item).length === 3 && 'title' in item && 'url' in item && 'index' in item;
3512
3571
  }
3513
3572
 
3514
- const ActiveIdContext = React.createContext(undefined);
3573
+ const ActiveItemContext = React.createContext({
3574
+ activeId: undefined,
3575
+ lastActiveIndex: '',
3576
+ setLastActiveIndex: () => { },
3577
+ });
3515
3578
  const LinkContext = React.createContext(undefined);
3516
3579
  LinkContext.displayName = 'LinkContext';
3517
3580
  const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefault, externalScrollbar = false, isInResponsiveMode = false, onLinkClick, }) => {
3581
+ const [lastActiveIndex, setLastActiveIndex] = useState('');
3582
+ const value = React.useMemo(() => ({
3583
+ lastActiveIndex,
3584
+ setLastActiveIndex,
3585
+ activeId,
3586
+ }), [lastActiveIndex, activeId]);
3587
+ const updateTocTree = React.useCallback((arr, parentId) => {
3588
+ return arr.map((item, key) => {
3589
+ let newItem = Object.assign(Object.assign({}, item), { index: parentId + key + '-' });
3590
+ if (isGroup(item) || isNodeGroup(item)) {
3591
+ newItem.items = updateTocTree(item.items, parentId + key + '-');
3592
+ }
3593
+ return newItem;
3594
+ });
3595
+ }, []);
3596
+ const updatedTree = updateTocTree(tree, '');
3518
3597
  const container = React.useRef(null);
3519
3598
  const child = React.useRef(null);
3520
3599
  const firstRender = useFirstRender();
@@ -3534,18 +3613,30 @@ const TableOfContents = React.memo(({ tree, activeId, Link, maxDepthOpenByDefaul
3534
3613
  return (React.createElement(Box, { ref: container, w: "full", bg: isInResponsiveMode ? 'canvas' : 'canvas-100', overflowY: "auto" },
3535
3614
  React.createElement(Box, { ref: child, my: 3 },
3536
3615
  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
- }))))));
3616
+ React.createElement(ActiveItemContext.Provider, { value: value },
3617
+ React.createElement(TOCContainer, { updatedTree: updatedTree }, updatedTree.map((item, key) => {
3618
+ if (isDivider(item)) {
3619
+ return React.createElement(Divider, { key: key, item: item, isInResponsiveMode: isInResponsiveMode });
3620
+ }
3621
+ return (React.createElement(GroupItem, { key: key, item: item, depth: 0, maxDepthOpenByDefault: maxDepthOpenByDefault, onLinkClick: onLinkClick, isInResponsiveMode: isInResponsiveMode }));
3622
+ })))))));
3543
3623
  });
3544
3624
  TableOfContents.displayName = 'TableOfContents';
3545
3625
  const Divider = React.memo(({ item, isInResponsiveMode = false }) => {
3546
3626
  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
3627
  });
3548
3628
  Divider.displayName = 'Divider';
3629
+ const TOCContainer = React.memo(({ children, updatedTree }) => {
3630
+ const { setLastActiveIndex } = React.useContext(ActiveItemContext);
3631
+ React.useEffect(() => {
3632
+ const firstNode = findFirstNode(updatedTree);
3633
+ if (firstNode) {
3634
+ setLastActiveIndex(firstNode.index);
3635
+ }
3636
+ }, []);
3637
+ return React.createElement(Box, null, children);
3638
+ });
3639
+ TOCContainer.displayName = 'TOCContainer';
3549
3640
  const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick }) => {
3550
3641
  if (isExternalLink(item)) {
3551
3642
  return (React.createElement(Box, { as: "a", href: item.url, target: "_blank", rel: "noopener noreferrer", display: "block" },
@@ -3563,9 +3654,24 @@ const GroupItem = React.memo(({ item, depth, maxDepthOpenByDefault, isInResponsi
3563
3654
  });
3564
3655
  GroupItem.displayName = 'GroupItem';
3565
3656
  const Group = React.memo(({ depth, item, maxDepthOpenByDefault, isInResponsiveMode, onLinkClick = () => { } }) => {
3566
- const activeId = React.useContext(ActiveIdContext);
3657
+ const { activeId, lastActiveIndex } = React.useContext(ActiveItemContext);
3567
3658
  const [isOpen, setIsOpen] = React.useState(() => isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault));
3568
- const hasActive = !!activeId && hasActiveItem(item.items, activeId);
3659
+ const isActiveGroup = React.useCallback((items, activeId, contextIndex) => {
3660
+ return items.some(element => {
3661
+ const hasSlugOrId = 'slug' in element || 'id' in element;
3662
+ const hasItems = 'items' in element && Array.isArray(element.items);
3663
+ if (!hasSlugOrId && !hasItems)
3664
+ return false;
3665
+ if (activeId &&
3666
+ 'index' in element &&
3667
+ (element.slug === activeId || element.id === activeId) &&
3668
+ element.index === contextIndex) {
3669
+ return true;
3670
+ }
3671
+ return hasItems ? isActiveGroup(element.items, activeId, contextIndex) : false;
3672
+ });
3673
+ }, []);
3674
+ const hasActive = isActiveGroup(item.items, activeId, lastActiveIndex);
3569
3675
  React.useEffect(() => {
3570
3676
  const openByDefault = isGroupOpenByDefault(depth, item, activeId, maxDepthOpenByDefault);
3571
3677
  if (isOpen !== openByDefault) {
@@ -3615,8 +3721,10 @@ const Item = React.memo(({ depth, isActive, id, title, meta, icon, isInResponsiv
3615
3721
  });
3616
3722
  Item.displayName = 'Item';
3617
3723
  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;
3724
+ const { activeId, lastActiveIndex, setLastActiveIndex } = React.useContext(ActiveItemContext);
3725
+ const { index } = item;
3726
+ const isSlugMatched = activeId === item.slug || activeId === item.id;
3727
+ const isActive = lastActiveIndex === index && isSlugMatched;
3620
3728
  const LinkComponent = React.useContext(LinkContext);
3621
3729
  const handleClick = (e) => {
3622
3730
  if (isActive) {
@@ -3624,6 +3732,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3624
3732
  e.preventDefault();
3625
3733
  }
3626
3734
  else {
3735
+ setLastActiveIndex(index);
3627
3736
  onLinkClick();
3628
3737
  }
3629
3738
  if (onClick) {
@@ -3631,7 +3740,7 @@ const Node = React.memo(({ item, depth, meta, showAsActive, isInResponsiveMode,
3631
3740
  }
3632
3741
  };
3633
3742
  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 })));
3743
+ 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
3744
  });
3636
3745
  Node.displayName = 'Node';
3637
3746
  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-alpha-0.2",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",