@capra/core 1.8.2 → 1.10.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.
Files changed (50) hide show
  1. package/dist/index.cjs +294 -46
  2. package/dist/index.d.cts +132 -20
  3. package/dist/index.d.mts +132 -20
  4. package/dist/index.mjs +295 -49
  5. package/dist/style.css +251 -72
  6. package/docs/core-alert--usage.md +2 -0
  7. package/docs/core-anchor--usage.md +2 -0
  8. package/docs/core-autocompletefield--usage.md +2 -0
  9. package/docs/core-badge--design.md +10 -5
  10. package/docs/core-badge--usage.md +5 -2
  11. package/docs/core-breadcrumbs--usage.md +2 -0
  12. package/docs/core-button--usage.md +2 -0
  13. package/docs/core-buttonlink--usage.md +2 -0
  14. package/docs/core-checkbox--usage.md +2 -0
  15. package/docs/core-collapse--usage.md +2 -0
  16. package/docs/core-datepickerfield--usage.md +2 -0
  17. package/docs/core-daterangepickerfield--usage.md +2 -0
  18. package/docs/core-divider--usage.md +2 -0
  19. package/docs/core-emptystate--usage.md +2 -0
  20. package/docs/core-helpertext--usage.md +2 -0
  21. package/docs/core-iconbutton--usage.md +2 -0
  22. package/docs/core-inputrow--usage.md +2 -0
  23. package/docs/core-label--usage.md +2 -0
  24. package/docs/core-link--usage.md +2 -0
  25. package/docs/core-listitem--usage.md +2 -0
  26. package/docs/core-menu--usage.md +2 -0
  27. package/docs/core-modal--usage.md +2 -0
  28. package/docs/core-pagination--usage.md +2 -0
  29. package/docs/core-pill--usage.md +2 -0
  30. package/docs/core-radio--usage.md +2 -0
  31. package/docs/core-radiogroup--usage.md +2 -0
  32. package/docs/core-radiotile--usage.md +2 -0
  33. package/docs/core-ribbon--usage.md +2 -0
  34. package/docs/core-skeleton--usage.md +1 -2
  35. package/docs/core-skeletongroup--usage.md +0 -1
  36. package/docs/core-spinner--usage.md +2 -0
  37. package/docs/core-switch--usage.md +2 -0
  38. package/docs/core-tabnav--usage.md +2 -0
  39. package/docs/core-tag--usage.md +2 -0
  40. package/docs/core-text--usage.md +2 -0
  41. package/docs/core-textarea--usage.md +2 -0
  42. package/docs/core-textinput--usage.md +2 -0
  43. package/docs/core-tooltip--usage.md +2 -0
  44. package/docs/core-topnav--usage.md +2 -0
  45. package/docs/core-tree--design.md +31 -0
  46. package/docs/core-tree--usage.md +102 -0
  47. package/docs/core-verticalnavigation--usage.md +2 -0
  48. package/docs/history-changelogs-capra-core--docs.md +34 -0
  49. package/docs/index.md +2 -0
  50. package/package.json +7 -7
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as React$1 from "react";
2
2
  import React, { Suspense, useCallback, useState } from "react";
3
- import { AnglesLeft, AnglesRight, ArrowUpRightFromSquare, AttentionOutlined, AttentionSolid, CalendarNextOutlined, CalendarOutlined, CalendarPrevOutlined, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, CircleXmark, CloseOutlined, DragGrip, Exclamation, EyeInvisibleOutlined, EyeOutlined, InfoOutlined, InfoSolid, Loading, SuccessOutlined, SuccessSolid, SwapRightOutlined, WarningOutlined, WarningSolid } from "@capra/icons";
4
- import { Breadcrumb as Breadcrumb$1, Breadcrumbs as Breadcrumbs$1, Button as Button$1, ButtonContext, Calendar, CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, ComboBox, DateInput, DatePicker, DatePickerStateContext, DateRangePicker, DateRangePickerStateContext, DateSegment, Dialog, DialogTrigger, Disclosure, DisclosurePanel, Focusable, Group, Header, Heading, HeadingContext, Input, InputContext, LabelContext, Link as Link$1, ListBox, ListBoxItem, Menu as Menu$1, MenuItem, MenuSection, MenuTrigger, Modal as Modal$1, ModalOverlay, NumberField as NumberField$1, OverlayArrow, OverlayTriggerStateContext, Popover as Popover$1, Pressable, RangeCalendar, RangeCalendarStateContext, RouterProvider, Separator, SubmenuTrigger, Text as Text$1, TextArea as TextArea$1, TextContext, TextField as TextField$1, Tooltip as Tooltip$1, TooltipTrigger, composeRenderProps, useContextProps, useSlottedContext } from "react-aria-components";
3
+ import { AnglesLeft, AnglesRight, ArrowUpRightFromSquare, AttentionOutlined, AttentionSolid, CalendarNextOutlined, CalendarOutlined, CalendarPrevOutlined, CaretRight, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, CircleXmark, CloseOutlined, DragGrip, Exclamation, EyeInvisibleOutlined, EyeOutlined, InfoOutlined, InfoSolid, Loading, SuccessOutlined, SuccessSolid, SwapRightOutlined, WarningOutlined, WarningSolid } from "@capra/icons";
4
+ import { Breadcrumb as Breadcrumb$1, Breadcrumbs as Breadcrumbs$1, Button as Button$1, ButtonContext, Calendar, CalendarCell, CalendarGrid, CalendarGridBody, CalendarGridHeader, CalendarHeaderCell, Collection, ComboBox, DateInput, DatePicker, DatePickerStateContext, DateRangePicker, DateRangePickerStateContext, DateSegment, Dialog, DialogTrigger, Disclosure, DisclosurePanel, Focusable, Group, Header, Heading, HeadingContext, Input, InputContext, LabelContext, Link as Link$1, ListBox, ListBoxItem, Menu as Menu$1, MenuItem, MenuSection, MenuTrigger, Modal as Modal$1, ModalOverlay, NumberField as NumberField$1, OverlayArrow, OverlayTriggerStateContext, Popover as Popover$1, Pressable, RangeCalendar, RangeCalendarStateContext, RouterProvider, Separator, SubmenuTrigger, Text as Text$1, TextArea as TextArea$1, TextContext, TextField as TextField$1, Tooltip as Tooltip$1, TooltipTrigger, Tree as Tree$1, TreeItem, TreeItemContent, composeRenderProps, useContextProps, useSlottedContext } from "react-aria-components";
5
5
  import { FocusScope, UNSAFE_PortalProvider, useDateFormatter, useFocusWithin, usePreventScroll } from "react-aria";
6
6
  import { createRoot } from "react-dom/client";
7
7
  import { createPortal } from "react-dom";
@@ -229,7 +229,7 @@ const VisuallyHidden = ({ children, ...props }) => {
229
229
  //#endregion
230
230
  //#region src/components/input-helpers/Label.tsx
231
231
  /** Label text and optional required indicator for form fields, aligned with Capra field layouts. */
232
- const Label$1 = React$1.forwardRef((props, ref) => {
232
+ const Label = React$1.forwardRef((props, ref) => {
233
233
  const [mergedProps, mergedRef] = useContextProps(props, ref, LabelContext);
234
234
  const { trailingSlot, children, required, FORCE__className: classNameOverride, style, ...labelProps } = mergedProps;
235
235
  if (!children) return null;
@@ -242,7 +242,7 @@ const Label$1 = React$1.forwardRef((props, ref) => {
242
242
  "aria-hidden": true
243
243
  }, "*"), /* @__PURE__ */ React$1.createElement(VisuallyHidden, null, "This field is required"))), trailingSlot && /* @__PURE__ */ React$1.createElement("span", { className: Label_module_default.trailingSlot }, trailingSlot));
244
244
  });
245
- Label$1.displayName = "Label";
245
+ Label.displayName = "Label";
246
246
  //#endregion
247
247
  //#region src/components/TextInput/TextInput.module.css
248
248
  var TextInput_module_default = {
@@ -372,7 +372,7 @@ function AutocompleteFieldWithoutRef(props, ref) {
372
372
  id,
373
373
  shouldFocusWrap: true,
374
374
  ref: comboboxRef
375
- }, /* @__PURE__ */ React.createElement(Label$1, null, label), /* @__PURE__ */ React.createElement(TextInput, {
375
+ }, /* @__PURE__ */ React.createElement(Label, null, label), /* @__PURE__ */ React.createElement(TextInput, {
376
376
  ...inputProps,
377
377
  ref,
378
378
  trailingSlot: trailingContent
@@ -554,15 +554,15 @@ const Card = Object.assign(CardRoot, {
554
554
  //#endregion
555
555
  //#region src/components/Badge/Badge.module.css
556
556
  var Badge_module_default = {
557
- "badge": "capra-Badge-module-yecu4W-badge",
558
- "base": "capra-Badge-module-yecu4W-base"
557
+ "badge": "capra-Badge-module-_3WihW-badge",
558
+ "base": "capra-Badge-module-_3WihW-base"
559
559
  };
560
560
  //#endregion
561
561
  //#region src/components/Badge/Badge.tsx
562
562
  /**
563
563
  * Badges display an indicator/counter on an associated component.
564
564
  */
565
- function Badge({ appearance = "danger", variant, count = 0, showZero = false, overflowCount = 99, FORCE__className, ...props }) {
565
+ function Badge({ appearance = "danger", variant = "counter", size = "md", count = 0, showZero = false, overflowCount = 99, FORCE__className, style, ...props }) {
566
566
  if (variant === "counter" && !showZero && !count) return null;
567
567
  const getBadgeContent = () => {
568
568
  if (variant === "dot") return null;
@@ -570,43 +570,55 @@ function Badge({ appearance = "danger", variant, count = 0, showZero = false, ov
570
570
  return value > overflowCount ? `${overflowCount}+` : value;
571
571
  };
572
572
  return /* @__PURE__ */ React$1.createElement("span", {
573
- role: "status",
574
573
  className: clsx(Badge_module_default.badge, FORCE__className),
575
574
  "data-appearance": appearance,
575
+ "data-size": size,
576
576
  "data-variant": variant,
577
+ style,
577
578
  ...props
578
579
  }, getBadgeContent());
579
580
  }
580
581
  /**
581
582
  * A convenience component allowing you to easily attach a badge to another component.
582
583
  */
583
- function BadgeLayout({ children }) {
584
- return /* @__PURE__ */ React$1.createElement("div", { className: Badge_module_default.base }, children);
584
+ function BadgeLayout({ children, offset = [0, 0] }) {
585
+ return /* @__PURE__ */ React$1.createElement("div", {
586
+ className: Badge_module_default.base,
587
+ style: {
588
+ "--_badge-offset-x": `${offset[0]}px`,
589
+ "--_badge-offset-y": `${offset[1]}px`
590
+ }
591
+ }, children);
585
592
  }
586
593
  //#endregion
587
594
  //#region src/components/ListItem/ListItem.module.css
588
595
  var ListItem_module_default = {
589
- "content": "capra-ListItem-module-VUh15W-content",
590
- "description": "capra-ListItem-module-VUh15W-description",
591
- "label": "capra-ListItem-module-VUh15W-label",
592
- "leading": "capra-ListItem-module-VUh15W-leading",
593
- "listItem": "capra-ListItem-module-VUh15W-listItem",
594
- "slot": "capra-ListItem-module-VUh15W-slot",
595
- "slots": "capra-ListItem-module-VUh15W-slots",
596
- "suffix": "capra-ListItem-module-VUh15W-suffix",
597
- "trailing": "capra-ListItem-module-VUh15W-trailing"
596
+ "__listItem-layout": "capra-ListItem-module-QN6vFW-__listItem-layout",
597
+ "content": "capra-ListItem-module-QN6vFW-content",
598
+ "description": "capra-ListItem-module-QN6vFW-description",
599
+ "label": "capra-ListItem-module-QN6vFW-label",
600
+ "leading": "capra-ListItem-module-QN6vFW-leading",
601
+ "listItem": "capra-ListItem-module-QN6vFW-listItem capra-ListItem-module-QN6vFW-__listItem-layout",
602
+ "slot": "capra-ListItem-module-QN6vFW-slot",
603
+ "slots": "capra-ListItem-module-QN6vFW-slots",
604
+ "suffix": "capra-ListItem-module-QN6vFW-suffix",
605
+ "trailing": "capra-ListItem-module-QN6vFW-trailing"
598
606
  };
599
607
  //#endregion
600
608
  //#region src/components/ListItem/ListItemSlots.tsx
609
+ const CollapsedSlot = "__CollapsedSlot__";
601
610
  const ListItemSlots = ({ children, trailing = false, FORCE__className }) => {
602
611
  if (React.Children.count(children) === 0) return null;
603
612
  return /* @__PURE__ */ React.createElement("div", {
604
613
  className: clsx(ListItem_module_default.slots, FORCE__className),
605
614
  "data-trailing": trailing || void 0
606
- }, React.Children.map(children, (child, index) => /* @__PURE__ */ React.createElement("div", {
607
- key: index,
608
- className: ListItem_module_default.slot
609
- }, child)));
615
+ }, React.Children.map(children, (child, index) => {
616
+ if (child === "__CollapsedSlot__") return void 0;
617
+ return /* @__PURE__ */ React.createElement("div", {
618
+ key: index,
619
+ className: ListItem_module_default.slot
620
+ }, child);
621
+ }));
610
622
  };
611
623
  //#endregion
612
624
  //#region src/components/ListItem/ListItem.tsx
@@ -629,7 +641,7 @@ const Trailing = ({ children, FORCE__className }) => {
629
641
  const Content = ({ children, FORCE__className }) => {
630
642
  return /* @__PURE__ */ React$1.createElement("div", { className: clsx(ListItem_module_default.content, FORCE__className) }, children);
631
643
  };
632
- const Label = ({ children, id }) => {
644
+ const Label$1 = ({ children, id }) => {
633
645
  return /* @__PURE__ */ React$1.createElement("div", {
634
646
  id,
635
647
  className: ListItem_module_default.label
@@ -648,7 +660,7 @@ const Spacer = () => {
648
660
  });
649
661
  };
650
662
  ListItem.Content = Content;
651
- ListItem.Label = Label;
663
+ ListItem.Label = Label$1;
652
664
  ListItem.Description = Description;
653
665
  ListItem.Suffix = Suffix;
654
666
  ListItem.Spacer = Spacer;
@@ -1089,7 +1101,7 @@ const TextField = React$1.forwardRef((props, ref) => {
1089
1101
  className: fieldLayout_module_default.field,
1090
1102
  "data-capra-field-root": "",
1091
1103
  "data-layout": layout
1092
- }, /* @__PURE__ */ React$1.createElement(Label$1, { required }, label), /* @__PURE__ */ React$1.createElement(TextInput, {
1104
+ }, /* @__PURE__ */ React$1.createElement(Label, { required }, label), /* @__PURE__ */ React$1.createElement(TextInput, {
1093
1105
  ref,
1094
1106
  ...inputRest,
1095
1107
  appearance,
@@ -1193,7 +1205,7 @@ const NumberField = React$1.forwardRef((props, ref) => {
1193
1205
  className: fieldLayout_module_default.field,
1194
1206
  "data-capra-field-root": "",
1195
1207
  "data-layout": layout
1196
- }, /* @__PURE__ */ React$1.createElement(Label$1, { required }, label), /* @__PURE__ */ React$1.createElement(Group, {
1208
+ }, /* @__PURE__ */ React$1.createElement(Label, { required }, label), /* @__PURE__ */ React$1.createElement(Group, {
1197
1209
  "data-capra-text-input": "",
1198
1210
  "data-size": size,
1199
1211
  className: clsx(TextInput_module_default.wrapper, NumberField_module_default.withStepper, classNameOverride)
@@ -2209,7 +2221,7 @@ function DatePickerFieldInner(props, ref) {
2209
2221
  isInvalid,
2210
2222
  shouldForceLeadingZeros: true,
2211
2223
  validationBehavior: "aria"
2212
- }, /* @__PURE__ */ React$1.createElement(Label$1, { required }, label), /* @__PURE__ */ React$1.createElement(DatePickerFieldRow, {
2224
+ }, /* @__PURE__ */ React$1.createElement(Label, { required }, label), /* @__PURE__ */ React$1.createElement(DatePickerFieldRow, {
2213
2225
  appearance,
2214
2226
  size,
2215
2227
  leadingSlot,
@@ -2451,7 +2463,7 @@ function DateRangePickerFieldInner(props, ref) {
2451
2463
  isInvalid,
2452
2464
  shouldForceLeadingZeros: true,
2453
2465
  validationBehavior: "aria"
2454
- }, /* @__PURE__ */ React$1.createElement(Label$1, { required }, label), /* @__PURE__ */ React$1.createElement(DateRangePickerFieldRow, {
2466
+ }, /* @__PURE__ */ React$1.createElement(Label, { required }, label), /* @__PURE__ */ React$1.createElement(DateRangePickerFieldRow, {
2455
2467
  appearance,
2456
2468
  size,
2457
2469
  leadingSlot,
@@ -2680,7 +2692,7 @@ const TextArea = React$1.forwardRef((props, ref) => {
2680
2692
  ...ariaFieldProps,
2681
2693
  className: fieldLayout_module_default.field,
2682
2694
  "data-layout": layout
2683
- }, /* @__PURE__ */ React$1.createElement(Label$1, { required }, label), /* @__PURE__ */ React$1.createElement("div", {
2695
+ }, /* @__PURE__ */ React$1.createElement(Label, { required }, label), /* @__PURE__ */ React$1.createElement("div", {
2684
2696
  className: clsx(TextArea_module_default.wrapper, classNameOverride),
2685
2697
  "data-has-indicator": hasIndicator,
2686
2698
  "data-autosize": autoSizeActive,
@@ -4357,23 +4369,23 @@ const submenuPanelClassName = Menu_module_default.menu;
4357
4369
  //#endregion
4358
4370
  //#region src/components/TabNav/TabNav.module.css
4359
4371
  var TabNav_module_default = {
4360
- "dropdownIcon": "capra-TabNav-module-qqfvea-dropdownIcon",
4361
- "extraContent": "capra-TabNav-module-qqfvea-extraContent",
4362
- "indentSpacer": "capra-TabNav-module-qqfvea-indentSpacer",
4363
- "panel": "capra-TabNav-module-qqfvea-panel",
4364
- "root": "capra-TabNav-module-qqfvea-root",
4365
- "subMenu": "capra-TabNav-module-qqfvea-subMenu",
4366
- "subMenuItem": "capra-TabNav-module-qqfvea-subMenuItem",
4367
- "subMenuItemActive": "capra-TabNav-module-qqfvea-subMenuItemActive",
4368
- "subTab": "capra-TabNav-module-qqfvea-subTab",
4369
- "subTabList": "capra-TabNav-module-qqfvea-subTabList",
4370
- "subTabListItem": "capra-TabNav-module-qqfvea-subTabListItem",
4371
- "tab": "capra-TabNav-module-qqfvea-tab",
4372
- "tabBar": "capra-TabNav-module-qqfvea-tabBar",
4373
- "tabGroup": "capra-TabNav-module-qqfvea-tabGroup",
4374
- "tabIcon": "capra-TabNav-module-qqfvea-tabIcon",
4375
- "tabLabel": "capra-TabNav-module-qqfvea-tabLabel",
4376
- "tabList": "capra-TabNav-module-qqfvea-tabList"
4372
+ "dropdownIcon": "capra-TabNav-module-pLDWhG-dropdownIcon",
4373
+ "extraContent": "capra-TabNav-module-pLDWhG-extraContent",
4374
+ "indentSpacer": "capra-TabNav-module-pLDWhG-indentSpacer",
4375
+ "panel": "capra-TabNav-module-pLDWhG-panel",
4376
+ "root": "capra-TabNav-module-pLDWhG-root",
4377
+ "subMenu": "capra-TabNav-module-pLDWhG-subMenu",
4378
+ "subMenuItem": "capra-TabNav-module-pLDWhG-subMenuItem",
4379
+ "subMenuItemActive": "capra-TabNav-module-pLDWhG-subMenuItemActive",
4380
+ "subTab": "capra-TabNav-module-pLDWhG-subTab",
4381
+ "subTabList": "capra-TabNav-module-pLDWhG-subTabList",
4382
+ "subTabListItem": "capra-TabNav-module-pLDWhG-subTabListItem",
4383
+ "tab": "capra-TabNav-module-pLDWhG-tab",
4384
+ "tabBar": "capra-TabNav-module-pLDWhG-tabBar",
4385
+ "tabGroup": "capra-TabNav-module-pLDWhG-tabGroup",
4386
+ "tabIcon": "capra-TabNav-module-pLDWhG-tabIcon",
4387
+ "tabLabel": "capra-TabNav-module-pLDWhG-tabLabel",
4388
+ "tabList": "capra-TabNav-module-pLDWhG-tabList"
4377
4389
  };
4378
4390
  //#endregion
4379
4391
  //#region src/components/TabNav/TabNav.tsx
@@ -4947,4 +4959,238 @@ function ArrowSvg() {
4947
4959
  }));
4948
4960
  }
4949
4961
  //#endregion
4950
- export { Alert, Anchor, AutocompleteField, Badge, BadgeLayout, Breadcrumb, Breadcrumbs, Button, ButtonLink, Card, Checkbox, Collapse, CustomTooltipTrigger, DatePickerField, DateRangePickerField, Divider, Drawer, EmptyState, IconButton, InputRow, Link, ListItem, Menu, Modal, NumberField, Pagination, PasswordField, Pill, Popover, Radio, RadioGroup, RadioTile, Ribbon, RouterProvider, SKELETON_SIZE, SKELETON_SIZE_TOKENS, Skeleton, SkeletonGroup, Spinner, Switch, TabNav, Tag, Text, TextArea, TextField, Toast, Tooltip, TopNav, VerticalNavigation, VisuallyHidden, submenuPanelClassName, tagColors };
4962
+ //#region src/components/Tree/Tree.module.css
4963
+ var Tree_module_default = {
4964
+ "chevronButton": "capra-Tree-module--hXpBa-chevronButton",
4965
+ "chevronIcon": "capra-Tree-module--hXpBa-chevronIcon",
4966
+ "indentSpacer": "capra-Tree-module--hXpBa-indentSpacer",
4967
+ "item": "capra-Tree-module--hXpBa-item capra-ListItem-module-QN6vFW-__listItem-layout",
4968
+ "itemContent": "capra-Tree-module--hXpBa-itemContent capra-ListItem-module-QN6vFW-content",
4969
+ "itemLabel": "capra-Tree-module--hXpBa-itemLabel capra-ListItem-module-QN6vFW-label",
4970
+ "itemSuffix": "capra-Tree-module--hXpBa-itemSuffix capra-ListItem-module-QN6vFW-suffix",
4971
+ "label": "capra-Tree-module--hXpBa-label",
4972
+ "root": "capra-Tree-module--hXpBa-root",
4973
+ "selectionCheckbox": "capra-Tree-module--hXpBa-selectionCheckbox",
4974
+ "suffix": "capra-Tree-module--hXpBa-suffix"
4975
+ };
4976
+ //#endregion
4977
+ //#region src/components/Tree/Tree.tsx
4978
+ const TreeSelectionContext = React$1.createContext(null);
4979
+ function getTextValue(item) {
4980
+ return typeof item.label === "string" ? item.label : String(item.key);
4981
+ }
4982
+ function buildTreeIndex(items) {
4983
+ const parentByKey = /* @__PURE__ */ new Map();
4984
+ const descendantsByKey = /* @__PURE__ */ new Map();
4985
+ const selectableDescendantsByKey = /* @__PURE__ */ new Map();
4986
+ const disabledKeys = /* @__PURE__ */ new Set();
4987
+ const selectableKeys = /* @__PURE__ */ new Set();
4988
+ const visit = (item, parent) => {
4989
+ parentByKey.set(item.key, parent);
4990
+ if (item.isDisabled) disabledKeys.add(item.key);
4991
+ else selectableKeys.add(item.key);
4992
+ const descendants = [];
4993
+ const selectableDescendants = [];
4994
+ for (const child of item.children ?? []) {
4995
+ visit(child, item.key);
4996
+ descendants.push(child.key, ...descendantsByKey.get(child.key) ?? []);
4997
+ if (!child.isDisabled) selectableDescendants.push(child.key);
4998
+ for (const descendant of selectableDescendantsByKey.get(child.key) ?? []) selectableDescendants.push(descendant);
4999
+ }
5000
+ descendantsByKey.set(item.key, descendants);
5001
+ selectableDescendantsByKey.set(item.key, selectableDescendants);
5002
+ };
5003
+ for (const item of items) visit(item, null);
5004
+ return {
5005
+ parentByKey,
5006
+ descendantsByKey,
5007
+ selectableDescendantsByKey,
5008
+ disabledKeys,
5009
+ selectableKeys
5010
+ };
5011
+ }
5012
+ function sanitizeSelection(selection, index) {
5013
+ const next = /* @__PURE__ */ new Set();
5014
+ for (const key of selection) if (index.parentByKey.has(key) && !index.disabledKeys.has(key)) next.add(key);
5015
+ return next;
5016
+ }
5017
+ function reconcileParentKeys(selection, index) {
5018
+ const next = new Set(selection);
5019
+ for (const [key, selectableDescendants] of index.selectableDescendantsByKey) {
5020
+ if (selectableDescendants.length === 0) continue;
5021
+ if (!selectableDescendants.every((descendantKey) => next.has(descendantKey))) next.delete(key);
5022
+ }
5023
+ return next;
5024
+ }
5025
+ function selectionToSet(selection, index) {
5026
+ if (selection === "all") return new Set(index.selectableKeys);
5027
+ if (selection == null) return /* @__PURE__ */ new Set();
5028
+ return sanitizeSelection(selection, index);
5029
+ }
5030
+ function expandKeysWithAncestors(keys, index) {
5031
+ if (keys == null) return;
5032
+ const expanded = /* @__PURE__ */ new Set();
5033
+ for (const key of keys) {
5034
+ if (!index.parentByKey.has(key)) continue;
5035
+ let current = key;
5036
+ while (current != null) {
5037
+ expanded.add(current);
5038
+ current = index.parentByKey.get(current) ?? null;
5039
+ }
5040
+ }
5041
+ return expanded;
5042
+ }
5043
+ function getCheckboxState(key, selectedKeys, index) {
5044
+ const selectableDescendants = index.selectableDescendantsByKey.get(key) ?? [];
5045
+ if (selectableDescendants.length === 0) return {
5046
+ checked: selectedKeys.has(key),
5047
+ indeterminate: false
5048
+ };
5049
+ const selectedDescendantCount = selectableDescendants.filter((descendantKey) => selectedKeys.has(descendantKey)).length;
5050
+ const allSelectableDescendantsSelected = selectedDescendantCount === selectableDescendants.length;
5051
+ const someSelectableDescendantsSelected = selectedDescendantCount > 0;
5052
+ if (allSelectableDescendantsSelected || selectedKeys.has(key)) return {
5053
+ checked: true,
5054
+ indeterminate: false
5055
+ };
5056
+ return {
5057
+ checked: false,
5058
+ indeterminate: someSelectableDescendantsSelected
5059
+ };
5060
+ }
5061
+ function applySelectionChange(prev, next, index) {
5062
+ const cascadedSelection = sanitizeSelection(next, index);
5063
+ for (const key of next) {
5064
+ if (prev.has(key) || index.disabledKeys.has(key)) continue;
5065
+ if ((index.descendantsByKey.get(key) ?? []).length === 0) continue;
5066
+ cascadedSelection.add(key);
5067
+ for (const descendantKey of index.selectableDescendantsByKey.get(key) ?? []) cascadedSelection.add(descendantKey);
5068
+ }
5069
+ for (const key of prev) {
5070
+ if (next.has(key) || index.disabledKeys.has(key)) continue;
5071
+ if ((index.descendantsByKey.get(key) ?? []).length === 0) continue;
5072
+ cascadedSelection.delete(key);
5073
+ for (const descendantKey of index.descendantsByKey.get(key) ?? []) cascadedSelection.delete(descendantKey);
5074
+ }
5075
+ return reconcileParentKeys(cascadedSelection, index);
5076
+ }
5077
+ function TreeSelectionCheckbox({ item }) {
5078
+ const context = React$1.useContext(TreeSelectionContext);
5079
+ if (context?.selectionMode !== "multiple") return null;
5080
+ const checkboxState = getCheckboxState(item.key, context.selectedKeys, context.index);
5081
+ return /* @__PURE__ */ React$1.createElement(Checkbox, {
5082
+ "aria-checked": checkboxState.indeterminate ? "mixed" : checkboxState.checked ? "true" : "false",
5083
+ "aria-label": getTextValue(item),
5084
+ checked: checkboxState.checked,
5085
+ disabled: context.index.disabledKeys.has(item.key),
5086
+ indeterminate: checkboxState.indeterminate,
5087
+ FORCE__className: Tree_module_default.selectionCheckbox,
5088
+ onChange: (event) => {
5089
+ event.stopPropagation();
5090
+ context.toggleSelection(item.key);
5091
+ },
5092
+ onClick: (event) => {
5093
+ event.stopPropagation();
5094
+ },
5095
+ onMouseDown: (event) => {
5096
+ event.stopPropagation();
5097
+ },
5098
+ onKeyDown: (event) => {
5099
+ event.stopPropagation();
5100
+ },
5101
+ onPointerDown: (event) => {
5102
+ event.stopPropagation();
5103
+ }
5104
+ });
5105
+ }
5106
+ function renderTreeItem(item) {
5107
+ return /* @__PURE__ */ React$1.createElement(TreeItem, {
5108
+ id: item.key,
5109
+ key: item.key,
5110
+ className: Tree_module_default.item,
5111
+ isDisabled: item.isDisabled,
5112
+ textValue: getTextValue(item)
5113
+ }, /* @__PURE__ */ React$1.createElement(TreeItemContent, null, ({ hasChildItems, id, level, selectionMode }) => /* @__PURE__ */ React$1.createElement(React$1.Fragment, null, /* @__PURE__ */ React$1.createElement(ListItem.Leading, null, Array.from({ length: Math.max(level - 1, 0) }).map((_, index) => /* @__PURE__ */ React$1.createElement("span", {
5114
+ key: `${String(item.key)}-indent-${index}`,
5115
+ "aria-hidden": "true",
5116
+ className: Tree_module_default.indentSpacer
5117
+ })), hasChildItems ? /* @__PURE__ */ React$1.createElement(Button$1, {
5118
+ slot: "chevron",
5119
+ className: Tree_module_default.chevronButton
5120
+ }, /* @__PURE__ */ React$1.createElement("span", {
5121
+ "aria-hidden": "true",
5122
+ className: Tree_module_default.chevronIcon
5123
+ }, /* @__PURE__ */ React$1.createElement(CaretRight, { size: "xs" }))) : /* @__PURE__ */ React$1.createElement("div", null), selectionMode === "multiple" ? /* @__PURE__ */ React$1.createElement(TreeSelectionCheckbox, { item }) : CollapsedSlot), /* @__PURE__ */ React$1.createElement("div", { className: Tree_module_default.itemContent }, /* @__PURE__ */ React$1.createElement("div", {
5124
+ id: String(id),
5125
+ className: Tree_module_default.itemLabel
5126
+ }, item.label)), /* @__PURE__ */ React$1.createElement(ListItem.Trailing, null, item.suffix ? /* @__PURE__ */ React$1.createElement("div", { className: Tree_module_default.itemSuffix }, item.suffix) : CollapsedSlot, item.trailingSlot || "__CollapsedSlot__"))), /* @__PURE__ */ React$1.createElement(Collection, { items: item.children }, renderTreeItem));
5127
+ }
5128
+ /**
5129
+ * A hierarchical tree with cascading multi-select and Capra ListItem row layout.
5130
+ */
5131
+ function Tree({ FORCE__className: classNameOverride, items, selectionMode = "multiple", defaultSelectedKeys, selectedKeys, onSelectionChange, expandedKeys, defaultExpandedKeys, ...props }) {
5132
+ const index = React$1.useMemo(() => buildTreeIndex(items), [items]);
5133
+ const resolvedExpandedKeys = React$1.useMemo(() => expandKeysWithAncestors(expandedKeys, index), [expandedKeys, index]);
5134
+ const resolvedDefaultExpandedKeys = React$1.useMemo(() => expandKeysWithAncestors(defaultExpandedKeys, index), [defaultExpandedKeys, index]);
5135
+ const [internalSelectedKeys, setInternalSelectedKeys] = React$1.useState(() => applySelectionChange(/* @__PURE__ */ new Set(), selectionToSet(selectedKeys ?? defaultSelectedKeys, index), index));
5136
+ React$1.useEffect(() => {
5137
+ const nextSelectedKeys = selectedKeys != null ? applySelectionChange(/* @__PURE__ */ new Set(), selectionToSet(selectedKeys, index), index) : reconcileParentKeys(sanitizeSelection(internalSelectedKeys, index), index);
5138
+ if (nextSelectedKeys.size !== internalSelectedKeys.size || Array.from(nextSelectedKeys).some((key) => !internalSelectedKeys.has(key))) setInternalSelectedKeys(nextSelectedKeys);
5139
+ }, [
5140
+ index,
5141
+ internalSelectedKeys,
5142
+ selectedKeys
5143
+ ]);
5144
+ const selectedKeysRef = React$1.useRef(internalSelectedKeys);
5145
+ selectedKeysRef.current = internalSelectedKeys;
5146
+ const commitSelection = React$1.useCallback((nextSelectedKeys) => {
5147
+ setInternalSelectedKeys(nextSelectedKeys);
5148
+ onSelectionChange?.(new Set(nextSelectedKeys));
5149
+ }, [onSelectionChange]);
5150
+ const toggleSelection = React$1.useCallback((key) => {
5151
+ if (selectionMode !== "multiple" || index.disabledKeys.has(key)) return;
5152
+ const nextSelectedKeys = new Set(selectedKeysRef.current);
5153
+ if (nextSelectedKeys.has(key)) nextSelectedKeys.delete(key);
5154
+ else nextSelectedKeys.add(key);
5155
+ commitSelection(applySelectionChange(selectedKeysRef.current, nextSelectedKeys, index));
5156
+ }, [
5157
+ commitSelection,
5158
+ index,
5159
+ selectionMode
5160
+ ]);
5161
+ const handleSelectionChange = React$1.useCallback((nextSelection) => {
5162
+ if (selectionMode !== "multiple") {
5163
+ commitSelection(selectionToSet(nextSelection, index));
5164
+ return;
5165
+ }
5166
+ commitSelection(applySelectionChange(selectedKeysRef.current, selectionToSet(nextSelection, index), index));
5167
+ }, [
5168
+ commitSelection,
5169
+ index,
5170
+ selectionMode
5171
+ ]);
5172
+ const selectionContext = React$1.useMemo(() => ({
5173
+ index,
5174
+ selectedKeys: internalSelectedKeys,
5175
+ selectionMode,
5176
+ toggleSelection
5177
+ }), [
5178
+ index,
5179
+ internalSelectedKeys,
5180
+ selectionMode,
5181
+ toggleSelection
5182
+ ]);
5183
+ return /* @__PURE__ */ React$1.createElement(TreeSelectionContext.Provider, { value: selectionContext }, /* @__PURE__ */ React$1.createElement(Tree$1, {
5184
+ ...props,
5185
+ selectionBehavior: "toggle",
5186
+ className: clsx(Tree_module_default.root, classNameOverride),
5187
+ items,
5188
+ selectedKeys: internalSelectedKeys,
5189
+ selectionMode,
5190
+ onSelectionChange: handleSelectionChange,
5191
+ expandedKeys: resolvedExpandedKeys,
5192
+ defaultExpandedKeys: resolvedDefaultExpandedKeys
5193
+ }, /* @__PURE__ */ React$1.createElement(Collection, { items }, renderTreeItem)));
5194
+ }
5195
+ //#endregion
5196
+ export { Alert, Anchor, AutocompleteField, Badge, BadgeLayout, Breadcrumb, Breadcrumbs, Button, ButtonLink, Card, Checkbox, Collapse, CustomTooltipTrigger, DatePickerField, DateRangePickerField, Divider, Drawer, EmptyState, IconButton, InputRow, Label, Link, ListItem, Menu, Modal, NumberField, Pagination, PasswordField, Pill, Popover, Radio, RadioGroup, RadioTile, Ribbon, RouterProvider, SKELETON_SIZE, SKELETON_SIZE_TOKENS, Skeleton, SkeletonGroup, Spinner, Switch, TabNav, Tag, Text, TextArea, TextField, Toast, Tooltip, TopNav, Tree, VerticalNavigation, VisuallyHidden, submenuPanelClassName, tagColors };