@capra/core 1.8.2 → 1.9.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 (49) hide show
  1. package/dist/index.cjs +264 -23
  2. package/dist/index.d.cts +119 -17
  3. package/dist/index.d.mts +119 -17
  4. package/dist/index.mjs +265 -26
  5. package/dist/style.css +186 -25
  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--usage.md +2 -0
  10. package/docs/core-breadcrumbs--usage.md +2 -0
  11. package/docs/core-button--usage.md +2 -0
  12. package/docs/core-buttonlink--usage.md +2 -0
  13. package/docs/core-checkbox--usage.md +2 -0
  14. package/docs/core-collapse--usage.md +2 -0
  15. package/docs/core-datepickerfield--usage.md +2 -0
  16. package/docs/core-daterangepickerfield--usage.md +2 -0
  17. package/docs/core-divider--usage.md +2 -0
  18. package/docs/core-emptystate--usage.md +2 -0
  19. package/docs/core-helpertext--usage.md +2 -0
  20. package/docs/core-iconbutton--usage.md +2 -0
  21. package/docs/core-inputrow--usage.md +2 -0
  22. package/docs/core-label--usage.md +2 -0
  23. package/docs/core-link--usage.md +2 -0
  24. package/docs/core-listitem--usage.md +2 -0
  25. package/docs/core-menu--usage.md +2 -0
  26. package/docs/core-modal--usage.md +2 -0
  27. package/docs/core-pagination--usage.md +2 -0
  28. package/docs/core-pill--usage.md +2 -0
  29. package/docs/core-radio--usage.md +2 -0
  30. package/docs/core-radiogroup--usage.md +2 -0
  31. package/docs/core-radiotile--usage.md +2 -0
  32. package/docs/core-ribbon--usage.md +2 -0
  33. package/docs/core-skeleton--usage.md +1 -2
  34. package/docs/core-skeletongroup--usage.md +0 -1
  35. package/docs/core-spinner--usage.md +2 -0
  36. package/docs/core-switch--usage.md +2 -0
  37. package/docs/core-tabnav--usage.md +2 -0
  38. package/docs/core-tag--usage.md +2 -0
  39. package/docs/core-text--usage.md +2 -0
  40. package/docs/core-textarea--usage.md +2 -0
  41. package/docs/core-textinput--usage.md +2 -0
  42. package/docs/core-tooltip--usage.md +2 -0
  43. package/docs/core-topnav--usage.md +2 -0
  44. package/docs/core-tree--design.md +31 -0
  45. package/docs/core-tree--usage.md +102 -0
  46. package/docs/core-verticalnavigation--usage.md +2 -0
  47. package/docs/history-changelogs-capra-core--docs.md +23 -0
  48. package/docs/index.md +2 -0
  49. package/package.json +7 -7
package/dist/index.cjs CHANGED
@@ -252,7 +252,7 @@ const VisuallyHidden = ({ children, ...props }) => {
252
252
  //#endregion
253
253
  //#region src/components/input-helpers/Label.tsx
254
254
  /** Label text and optional required indicator for form fields, aligned with Capra field layouts. */
255
- const Label$1 = react.forwardRef((props, ref) => {
255
+ const Label = react.forwardRef((props, ref) => {
256
256
  const [mergedProps, mergedRef] = (0, react_aria_components.useContextProps)(props, ref, react_aria_components.LabelContext);
257
257
  const { trailingSlot, children, required, FORCE__className: classNameOverride, style, ...labelProps } = mergedProps;
258
258
  if (!children) return null;
@@ -265,7 +265,7 @@ const Label$1 = react.forwardRef((props, ref) => {
265
265
  "aria-hidden": true
266
266
  }, "*"), /* @__PURE__ */ react.createElement(VisuallyHidden, null, "This field is required"))), trailingSlot && /* @__PURE__ */ react.createElement("span", { className: Label_module_default.trailingSlot }, trailingSlot));
267
267
  });
268
- Label$1.displayName = "Label";
268
+ Label.displayName = "Label";
269
269
  //#endregion
270
270
  //#region src/components/TextInput/TextInput.module.css
271
271
  var TextInput_module_default = {
@@ -395,7 +395,7 @@ function AutocompleteFieldWithoutRef(props, ref) {
395
395
  id,
396
396
  shouldFocusWrap: true,
397
397
  ref: comboboxRef
398
- }, /* @__PURE__ */ react.default.createElement(Label$1, null, label), /* @__PURE__ */ react.default.createElement(TextInput, {
398
+ }, /* @__PURE__ */ react.default.createElement(Label, null, label), /* @__PURE__ */ react.default.createElement(TextInput, {
399
399
  ...inputProps,
400
400
  ref,
401
401
  trailingSlot: trailingContent
@@ -609,27 +609,32 @@ function BadgeLayout({ children }) {
609
609
  //#endregion
610
610
  //#region src/components/ListItem/ListItem.module.css
611
611
  var ListItem_module_default = {
612
- "content": "capra-ListItem-module-VUh15W-content",
613
- "description": "capra-ListItem-module-VUh15W-description",
614
- "label": "capra-ListItem-module-VUh15W-label",
615
- "leading": "capra-ListItem-module-VUh15W-leading",
616
- "listItem": "capra-ListItem-module-VUh15W-listItem",
617
- "slot": "capra-ListItem-module-VUh15W-slot",
618
- "slots": "capra-ListItem-module-VUh15W-slots",
619
- "suffix": "capra-ListItem-module-VUh15W-suffix",
620
- "trailing": "capra-ListItem-module-VUh15W-trailing"
612
+ "__listItem-layout": "capra-ListItem-module-QN6vFW-__listItem-layout",
613
+ "content": "capra-ListItem-module-QN6vFW-content",
614
+ "description": "capra-ListItem-module-QN6vFW-description",
615
+ "label": "capra-ListItem-module-QN6vFW-label",
616
+ "leading": "capra-ListItem-module-QN6vFW-leading",
617
+ "listItem": "capra-ListItem-module-QN6vFW-listItem capra-ListItem-module-QN6vFW-__listItem-layout",
618
+ "slot": "capra-ListItem-module-QN6vFW-slot",
619
+ "slots": "capra-ListItem-module-QN6vFW-slots",
620
+ "suffix": "capra-ListItem-module-QN6vFW-suffix",
621
+ "trailing": "capra-ListItem-module-QN6vFW-trailing"
621
622
  };
622
623
  //#endregion
623
624
  //#region src/components/ListItem/ListItemSlots.tsx
625
+ const CollapsedSlot = "__CollapsedSlot__";
624
626
  const ListItemSlots = ({ children, trailing = false, FORCE__className }) => {
625
627
  if (react.default.Children.count(children) === 0) return null;
626
628
  return /* @__PURE__ */ react.default.createElement("div", {
627
629
  className: clsx(ListItem_module_default.slots, FORCE__className),
628
630
  "data-trailing": trailing || void 0
629
- }, react.default.Children.map(children, (child, index) => /* @__PURE__ */ react.default.createElement("div", {
630
- key: index,
631
- className: ListItem_module_default.slot
632
- }, child)));
631
+ }, react.default.Children.map(children, (child, index) => {
632
+ if (child === "__CollapsedSlot__") return void 0;
633
+ return /* @__PURE__ */ react.default.createElement("div", {
634
+ key: index,
635
+ className: ListItem_module_default.slot
636
+ }, child);
637
+ }));
633
638
  };
634
639
  //#endregion
635
640
  //#region src/components/ListItem/ListItem.tsx
@@ -652,7 +657,7 @@ const Trailing = ({ children, FORCE__className }) => {
652
657
  const Content = ({ children, FORCE__className }) => {
653
658
  return /* @__PURE__ */ react.createElement("div", { className: clsx(ListItem_module_default.content, FORCE__className) }, children);
654
659
  };
655
- const Label = ({ children, id }) => {
660
+ const Label$1 = ({ children, id }) => {
656
661
  return /* @__PURE__ */ react.createElement("div", {
657
662
  id,
658
663
  className: ListItem_module_default.label
@@ -671,7 +676,7 @@ const Spacer = () => {
671
676
  });
672
677
  };
673
678
  ListItem.Content = Content;
674
- ListItem.Label = Label;
679
+ ListItem.Label = Label$1;
675
680
  ListItem.Description = Description;
676
681
  ListItem.Suffix = Suffix;
677
682
  ListItem.Spacer = Spacer;
@@ -1112,7 +1117,7 @@ const TextField = react.forwardRef((props, ref) => {
1112
1117
  className: fieldLayout_module_default.field,
1113
1118
  "data-capra-field-root": "",
1114
1119
  "data-layout": layout
1115
- }, /* @__PURE__ */ react.createElement(Label$1, { required }, label), /* @__PURE__ */ react.createElement(TextInput, {
1120
+ }, /* @__PURE__ */ react.createElement(Label, { required }, label), /* @__PURE__ */ react.createElement(TextInput, {
1116
1121
  ref,
1117
1122
  ...inputRest,
1118
1123
  appearance,
@@ -1216,7 +1221,7 @@ const NumberField = react.forwardRef((props, ref) => {
1216
1221
  className: fieldLayout_module_default.field,
1217
1222
  "data-capra-field-root": "",
1218
1223
  "data-layout": layout
1219
- }, /* @__PURE__ */ react.createElement(Label$1, { required }, label), /* @__PURE__ */ react.createElement(react_aria_components.Group, {
1224
+ }, /* @__PURE__ */ react.createElement(Label, { required }, label), /* @__PURE__ */ react.createElement(react_aria_components.Group, {
1220
1225
  "data-capra-text-input": "",
1221
1226
  "data-size": size,
1222
1227
  className: clsx(TextInput_module_default.wrapper, NumberField_module_default.withStepper, classNameOverride)
@@ -2232,7 +2237,7 @@ function DatePickerFieldInner(props, ref) {
2232
2237
  isInvalid,
2233
2238
  shouldForceLeadingZeros: true,
2234
2239
  validationBehavior: "aria"
2235
- }, /* @__PURE__ */ react.createElement(Label$1, { required }, label), /* @__PURE__ */ react.createElement(DatePickerFieldRow, {
2240
+ }, /* @__PURE__ */ react.createElement(Label, { required }, label), /* @__PURE__ */ react.createElement(DatePickerFieldRow, {
2236
2241
  appearance,
2237
2242
  size,
2238
2243
  leadingSlot,
@@ -2474,7 +2479,7 @@ function DateRangePickerFieldInner(props, ref) {
2474
2479
  isInvalid,
2475
2480
  shouldForceLeadingZeros: true,
2476
2481
  validationBehavior: "aria"
2477
- }, /* @__PURE__ */ react.createElement(Label$1, { required }, label), /* @__PURE__ */ react.createElement(DateRangePickerFieldRow, {
2482
+ }, /* @__PURE__ */ react.createElement(Label, { required }, label), /* @__PURE__ */ react.createElement(DateRangePickerFieldRow, {
2478
2483
  appearance,
2479
2484
  size,
2480
2485
  leadingSlot,
@@ -2703,7 +2708,7 @@ const TextArea = react.forwardRef((props, ref) => {
2703
2708
  ...ariaFieldProps,
2704
2709
  className: fieldLayout_module_default.field,
2705
2710
  "data-layout": layout
2706
- }, /* @__PURE__ */ react.createElement(Label$1, { required }, label), /* @__PURE__ */ react.createElement("div", {
2711
+ }, /* @__PURE__ */ react.createElement(Label, { required }, label), /* @__PURE__ */ react.createElement("div", {
2707
2712
  className: clsx(TextArea_module_default.wrapper, classNameOverride),
2708
2713
  "data-has-indicator": hasIndicator,
2709
2714
  "data-autosize": autoSizeActive,
@@ -4970,6 +4975,240 @@ function ArrowSvg() {
4970
4975
  }));
4971
4976
  }
4972
4977
  //#endregion
4978
+ //#region src/components/Tree/Tree.module.css
4979
+ var Tree_module_default = {
4980
+ "chevronButton": "capra-Tree-module--hXpBa-chevronButton",
4981
+ "chevronIcon": "capra-Tree-module--hXpBa-chevronIcon",
4982
+ "indentSpacer": "capra-Tree-module--hXpBa-indentSpacer",
4983
+ "item": "capra-Tree-module--hXpBa-item capra-ListItem-module-QN6vFW-__listItem-layout",
4984
+ "itemContent": "capra-Tree-module--hXpBa-itemContent capra-ListItem-module-QN6vFW-content",
4985
+ "itemLabel": "capra-Tree-module--hXpBa-itemLabel capra-ListItem-module-QN6vFW-label",
4986
+ "itemSuffix": "capra-Tree-module--hXpBa-itemSuffix capra-ListItem-module-QN6vFW-suffix",
4987
+ "label": "capra-Tree-module--hXpBa-label",
4988
+ "root": "capra-Tree-module--hXpBa-root",
4989
+ "selectionCheckbox": "capra-Tree-module--hXpBa-selectionCheckbox",
4990
+ "suffix": "capra-Tree-module--hXpBa-suffix"
4991
+ };
4992
+ //#endregion
4993
+ //#region src/components/Tree/Tree.tsx
4994
+ const TreeSelectionContext = react.createContext(null);
4995
+ function getTextValue(item) {
4996
+ return typeof item.label === "string" ? item.label : String(item.key);
4997
+ }
4998
+ function buildTreeIndex(items) {
4999
+ const parentByKey = /* @__PURE__ */ new Map();
5000
+ const descendantsByKey = /* @__PURE__ */ new Map();
5001
+ const selectableDescendantsByKey = /* @__PURE__ */ new Map();
5002
+ const disabledKeys = /* @__PURE__ */ new Set();
5003
+ const selectableKeys = /* @__PURE__ */ new Set();
5004
+ const visit = (item, parent) => {
5005
+ parentByKey.set(item.key, parent);
5006
+ if (item.isDisabled) disabledKeys.add(item.key);
5007
+ else selectableKeys.add(item.key);
5008
+ const descendants = [];
5009
+ const selectableDescendants = [];
5010
+ for (const child of item.children ?? []) {
5011
+ visit(child, item.key);
5012
+ descendants.push(child.key, ...descendantsByKey.get(child.key) ?? []);
5013
+ if (!child.isDisabled) selectableDescendants.push(child.key);
5014
+ for (const descendant of selectableDescendantsByKey.get(child.key) ?? []) selectableDescendants.push(descendant);
5015
+ }
5016
+ descendantsByKey.set(item.key, descendants);
5017
+ selectableDescendantsByKey.set(item.key, selectableDescendants);
5018
+ };
5019
+ for (const item of items) visit(item, null);
5020
+ return {
5021
+ parentByKey,
5022
+ descendantsByKey,
5023
+ selectableDescendantsByKey,
5024
+ disabledKeys,
5025
+ selectableKeys
5026
+ };
5027
+ }
5028
+ function sanitizeSelection(selection, index) {
5029
+ const next = /* @__PURE__ */ new Set();
5030
+ for (const key of selection) if (index.parentByKey.has(key) && !index.disabledKeys.has(key)) next.add(key);
5031
+ return next;
5032
+ }
5033
+ function reconcileParentKeys(selection, index) {
5034
+ const next = new Set(selection);
5035
+ for (const [key, selectableDescendants] of index.selectableDescendantsByKey) {
5036
+ if (selectableDescendants.length === 0) continue;
5037
+ if (!selectableDescendants.every((descendantKey) => next.has(descendantKey))) next.delete(key);
5038
+ }
5039
+ return next;
5040
+ }
5041
+ function selectionToSet(selection, index) {
5042
+ if (selection === "all") return new Set(index.selectableKeys);
5043
+ if (selection == null) return /* @__PURE__ */ new Set();
5044
+ return sanitizeSelection(selection, index);
5045
+ }
5046
+ function expandKeysWithAncestors(keys, index) {
5047
+ if (keys == null) return;
5048
+ const expanded = /* @__PURE__ */ new Set();
5049
+ for (const key of keys) {
5050
+ if (!index.parentByKey.has(key)) continue;
5051
+ let current = key;
5052
+ while (current != null) {
5053
+ expanded.add(current);
5054
+ current = index.parentByKey.get(current) ?? null;
5055
+ }
5056
+ }
5057
+ return expanded;
5058
+ }
5059
+ function getCheckboxState(key, selectedKeys, index) {
5060
+ const selectableDescendants = index.selectableDescendantsByKey.get(key) ?? [];
5061
+ if (selectableDescendants.length === 0) return {
5062
+ checked: selectedKeys.has(key),
5063
+ indeterminate: false
5064
+ };
5065
+ const selectedDescendantCount = selectableDescendants.filter((descendantKey) => selectedKeys.has(descendantKey)).length;
5066
+ const allSelectableDescendantsSelected = selectedDescendantCount === selectableDescendants.length;
5067
+ const someSelectableDescendantsSelected = selectedDescendantCount > 0;
5068
+ if (allSelectableDescendantsSelected || selectedKeys.has(key)) return {
5069
+ checked: true,
5070
+ indeterminate: false
5071
+ };
5072
+ return {
5073
+ checked: false,
5074
+ indeterminate: someSelectableDescendantsSelected
5075
+ };
5076
+ }
5077
+ function applySelectionChange(prev, next, index) {
5078
+ const cascadedSelection = sanitizeSelection(next, index);
5079
+ for (const key of next) {
5080
+ if (prev.has(key) || index.disabledKeys.has(key)) continue;
5081
+ if ((index.descendantsByKey.get(key) ?? []).length === 0) continue;
5082
+ cascadedSelection.add(key);
5083
+ for (const descendantKey of index.selectableDescendantsByKey.get(key) ?? []) cascadedSelection.add(descendantKey);
5084
+ }
5085
+ for (const key of prev) {
5086
+ if (next.has(key) || index.disabledKeys.has(key)) continue;
5087
+ if ((index.descendantsByKey.get(key) ?? []).length === 0) continue;
5088
+ cascadedSelection.delete(key);
5089
+ for (const descendantKey of index.descendantsByKey.get(key) ?? []) cascadedSelection.delete(descendantKey);
5090
+ }
5091
+ return reconcileParentKeys(cascadedSelection, index);
5092
+ }
5093
+ function TreeSelectionCheckbox({ item }) {
5094
+ const context = react.useContext(TreeSelectionContext);
5095
+ if (context?.selectionMode !== "multiple") return null;
5096
+ const checkboxState = getCheckboxState(item.key, context.selectedKeys, context.index);
5097
+ return /* @__PURE__ */ react.createElement(Checkbox, {
5098
+ "aria-checked": checkboxState.indeterminate ? "mixed" : checkboxState.checked ? "true" : "false",
5099
+ "aria-label": getTextValue(item),
5100
+ checked: checkboxState.checked,
5101
+ disabled: context.index.disabledKeys.has(item.key),
5102
+ indeterminate: checkboxState.indeterminate,
5103
+ FORCE__className: Tree_module_default.selectionCheckbox,
5104
+ onChange: (event) => {
5105
+ event.stopPropagation();
5106
+ context.toggleSelection(item.key);
5107
+ },
5108
+ onClick: (event) => {
5109
+ event.stopPropagation();
5110
+ },
5111
+ onMouseDown: (event) => {
5112
+ event.stopPropagation();
5113
+ },
5114
+ onKeyDown: (event) => {
5115
+ event.stopPropagation();
5116
+ },
5117
+ onPointerDown: (event) => {
5118
+ event.stopPropagation();
5119
+ }
5120
+ });
5121
+ }
5122
+ function renderTreeItem(item) {
5123
+ return /* @__PURE__ */ react.createElement(react_aria_components.TreeItem, {
5124
+ id: item.key,
5125
+ key: item.key,
5126
+ className: Tree_module_default.item,
5127
+ isDisabled: item.isDisabled,
5128
+ textValue: getTextValue(item)
5129
+ }, /* @__PURE__ */ react.createElement(react_aria_components.TreeItemContent, null, ({ hasChildItems, id, level, selectionMode }) => /* @__PURE__ */ react.createElement(react.Fragment, null, /* @__PURE__ */ react.createElement(ListItem.Leading, null, Array.from({ length: Math.max(level - 1, 0) }).map((_, index) => /* @__PURE__ */ react.createElement("span", {
5130
+ key: `${String(item.key)}-indent-${index}`,
5131
+ "aria-hidden": "true",
5132
+ className: Tree_module_default.indentSpacer
5133
+ })), hasChildItems ? /* @__PURE__ */ react.createElement(react_aria_components.Button, {
5134
+ slot: "chevron",
5135
+ className: Tree_module_default.chevronButton
5136
+ }, /* @__PURE__ */ react.createElement("span", {
5137
+ "aria-hidden": "true",
5138
+ className: Tree_module_default.chevronIcon
5139
+ }, /* @__PURE__ */ react.createElement(_capra_icons.CaretRight, { size: "xs" }))) : /* @__PURE__ */ react.createElement("div", null), selectionMode === "multiple" ? /* @__PURE__ */ react.createElement(TreeSelectionCheckbox, { item }) : CollapsedSlot), /* @__PURE__ */ react.createElement("div", { className: Tree_module_default.itemContent }, /* @__PURE__ */ react.createElement("div", {
5140
+ id: String(id),
5141
+ className: Tree_module_default.itemLabel
5142
+ }, item.label)), /* @__PURE__ */ react.createElement(ListItem.Trailing, null, item.suffix ? /* @__PURE__ */ react.createElement("div", { className: Tree_module_default.itemSuffix }, item.suffix) : CollapsedSlot, item.trailingSlot || "__CollapsedSlot__"))), /* @__PURE__ */ react.createElement(react_aria_components.Collection, { items: item.children }, renderTreeItem));
5143
+ }
5144
+ /**
5145
+ * A hierarchical tree with cascading multi-select and Capra ListItem row layout.
5146
+ */
5147
+ function Tree({ FORCE__className: classNameOverride, items, selectionMode = "multiple", defaultSelectedKeys, selectedKeys, onSelectionChange, expandedKeys, defaultExpandedKeys, ...props }) {
5148
+ const index = react.useMemo(() => buildTreeIndex(items), [items]);
5149
+ const resolvedExpandedKeys = react.useMemo(() => expandKeysWithAncestors(expandedKeys, index), [expandedKeys, index]);
5150
+ const resolvedDefaultExpandedKeys = react.useMemo(() => expandKeysWithAncestors(defaultExpandedKeys, index), [defaultExpandedKeys, index]);
5151
+ const [internalSelectedKeys, setInternalSelectedKeys] = react.useState(() => applySelectionChange(/* @__PURE__ */ new Set(), selectionToSet(selectedKeys ?? defaultSelectedKeys, index), index));
5152
+ react.useEffect(() => {
5153
+ const nextSelectedKeys = selectedKeys != null ? applySelectionChange(/* @__PURE__ */ new Set(), selectionToSet(selectedKeys, index), index) : reconcileParentKeys(sanitizeSelection(internalSelectedKeys, index), index);
5154
+ if (nextSelectedKeys.size !== internalSelectedKeys.size || Array.from(nextSelectedKeys).some((key) => !internalSelectedKeys.has(key))) setInternalSelectedKeys(nextSelectedKeys);
5155
+ }, [
5156
+ index,
5157
+ internalSelectedKeys,
5158
+ selectedKeys
5159
+ ]);
5160
+ const selectedKeysRef = react.useRef(internalSelectedKeys);
5161
+ selectedKeysRef.current = internalSelectedKeys;
5162
+ const commitSelection = react.useCallback((nextSelectedKeys) => {
5163
+ setInternalSelectedKeys(nextSelectedKeys);
5164
+ onSelectionChange?.(new Set(nextSelectedKeys));
5165
+ }, [onSelectionChange]);
5166
+ const toggleSelection = react.useCallback((key) => {
5167
+ if (selectionMode !== "multiple" || index.disabledKeys.has(key)) return;
5168
+ const nextSelectedKeys = new Set(selectedKeysRef.current);
5169
+ if (nextSelectedKeys.has(key)) nextSelectedKeys.delete(key);
5170
+ else nextSelectedKeys.add(key);
5171
+ commitSelection(applySelectionChange(selectedKeysRef.current, nextSelectedKeys, index));
5172
+ }, [
5173
+ commitSelection,
5174
+ index,
5175
+ selectionMode
5176
+ ]);
5177
+ const handleSelectionChange = react.useCallback((nextSelection) => {
5178
+ if (selectionMode !== "multiple") {
5179
+ commitSelection(selectionToSet(nextSelection, index));
5180
+ return;
5181
+ }
5182
+ commitSelection(applySelectionChange(selectedKeysRef.current, selectionToSet(nextSelection, index), index));
5183
+ }, [
5184
+ commitSelection,
5185
+ index,
5186
+ selectionMode
5187
+ ]);
5188
+ const selectionContext = react.useMemo(() => ({
5189
+ index,
5190
+ selectedKeys: internalSelectedKeys,
5191
+ selectionMode,
5192
+ toggleSelection
5193
+ }), [
5194
+ index,
5195
+ internalSelectedKeys,
5196
+ selectionMode,
5197
+ toggleSelection
5198
+ ]);
5199
+ return /* @__PURE__ */ react.createElement(TreeSelectionContext.Provider, { value: selectionContext }, /* @__PURE__ */ react.createElement(react_aria_components.Tree, {
5200
+ ...props,
5201
+ selectionBehavior: "toggle",
5202
+ className: clsx(Tree_module_default.root, classNameOverride),
5203
+ items,
5204
+ selectedKeys: internalSelectedKeys,
5205
+ selectionMode,
5206
+ onSelectionChange: handleSelectionChange,
5207
+ expandedKeys: resolvedExpandedKeys,
5208
+ defaultExpandedKeys: resolvedDefaultExpandedKeys
5209
+ }, /* @__PURE__ */ react.createElement(react_aria_components.Collection, { items }, renderTreeItem)));
5210
+ }
5211
+ //#endregion
4973
5212
  exports.Alert = Alert;
4974
5213
  exports.Anchor = Anchor;
4975
5214
  exports.AutocompleteField = AutocompleteField;
@@ -4990,6 +5229,7 @@ exports.Drawer = Drawer;
4990
5229
  exports.EmptyState = EmptyState;
4991
5230
  exports.IconButton = IconButton;
4992
5231
  exports.InputRow = InputRow;
5232
+ exports.Label = Label;
4993
5233
  exports.Link = Link;
4994
5234
  exports.ListItem = ListItem;
4995
5235
  exports.Menu = Menu;
@@ -5023,6 +5263,7 @@ exports.TextField = TextField;
5023
5263
  exports.Toast = Toast;
5024
5264
  exports.Tooltip = Tooltip;
5025
5265
  exports.TopNav = TopNav;
5266
+ exports.Tree = Tree;
5026
5267
  exports.VerticalNavigation = VerticalNavigation;
5027
5268
  exports.VisuallyHidden = VisuallyHidden;
5028
5269
  exports.submenuPanelClassName = submenuPanelClassName;
package/dist/index.d.cts CHANGED
@@ -1,10 +1,14 @@
1
1
  import * as React$2 from "react";
2
2
  import React$1, { HTMLAttributeAnchorTarget, HTMLAttributeReferrerPolicy } from "react";
3
- import { BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1, ButtonProps as ButtonProps$1, ComboBoxRenderProps, DatePickerProps, DateRangePickerProps, DateValue, DisclosureProps, Focusable, LinkProps as LinkProps$1, ListBoxItemProps, PopoverProps as PopoverProps$1, PressEvent, RouterProvider } from "react-aria-components";
3
+ import { BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1, ButtonProps as ButtonProps$1, ComboBoxRenderProps, DatePickerProps, DateRangePickerProps, DateValue, DisclosureProps, Focusable, Key, LinkProps as LinkProps$1, ListBoxItemProps, PopoverProps as PopoverProps$1, PressEvent, RouterProvider } from "react-aria-components";
4
4
  import { SvgIcon } from "@capra/icons";
5
5
  import { SvgLogo } from "@capra/icons/logos";
6
6
  //#region src/utils/stylingOverride.d.ts
7
7
  interface StylingOverrideProps {
8
+ /** Use `FORCE__className` instead. */
9
+ className?: never;
10
+ /** Inline styles are not supported; use component props or `FORCE__className`. */
11
+ style?: never;
8
12
  /**
9
13
  * 🚨 This prop is meant to be an escape hatch. 🚨
10
14
  *
@@ -208,7 +212,7 @@ type TextProps<As extends React$2.ElementType> = {
208
212
  * The underlying element rendered by the component. Defaults to `span`.
209
213
  */
210
214
  as?: As;
211
- } & StylingOverrideProps & Omit<React$2.ComponentPropsWithoutRef<As>, 'className'>;
215
+ } & StylingOverrideProps & React$2.ComponentPropsWithoutRef<As>;
212
216
  /**
213
217
  * Component for displaying text. The visual display can be controlled via
214
218
  * `variant`. The underlying HTML element can be controlled via the `as` prop,
@@ -228,7 +232,7 @@ declare const Text: <As extends React$2.ElementType = "span">(props: {
228
232
  * The underlying element rendered by the component. Defaults to `span`.
229
233
  */
230
234
  as?: As | undefined;
231
- } & StylingOverrideProps & Omit<React$2.PropsWithoutRef<React$2.ComponentProps<As>>, "className"> & React$2.RefAttributes<unknown>) => React$2.ReactElement;
235
+ } & StylingOverrideProps & React$2.PropsWithoutRef<React$2.ComponentProps<As>> & React$2.RefAttributes<unknown>) => React$2.ReactElement;
232
236
  //#endregion
233
237
  //#region src/components/Card/Card.d.ts
234
238
  /**
@@ -345,7 +349,7 @@ type ListItemProps<As extends React$2.ElementType> = {
345
349
  declare function ListItem<As extends React$2.ElementType = 'li'>({ as: asComponent, children, FORCE__className: classNameOverride, ...props }: ListItemProps<As>): React$2.JSX.Element;
346
350
  declare namespace ListItem {
347
351
  export { Content };
348
- export { Label };
352
+ export { Label$1 as Label };
349
353
  export { Description };
350
354
  export { Suffix };
351
355
  export { Spacer };
@@ -358,7 +362,7 @@ declare const Content: ({ children, FORCE__className }: React$2.PropsWithChildre
358
362
  type ListItemLabelProps = React$2.PropsWithChildren & {
359
363
  id?: string;
360
364
  };
361
- declare const Label: ({ children, id }: ListItemLabelProps) => React$2.JSX.Element;
365
+ declare const Label$1: ({ children, id }: ListItemLabelProps) => React$2.JSX.Element;
362
366
  declare const Suffix: ({ children }: React$2.PropsWithChildren) => React$2.JSX.Element;
363
367
  declare const Description: ({ children }: React$2.PropsWithChildren) => React$2.JSX.Element;
364
368
  declare const Spacer: () => React$2.JSX.Element;
@@ -450,11 +454,11 @@ type ChildrenLabel = {
450
454
  /**
451
455
  * Require either 'aria-label', 'aria-labelledby', or 'children' for accessibility
452
456
  */
453
- type LabelProps = AccessibleLabelProps | ChildrenLabel;
457
+ type LabelProps$1 = AccessibleLabelProps | ChildrenLabel;
454
458
  type RadioProps = {
455
459
  /** The value of the radio button. */
456
460
  value: string | null;
457
- } & Partial<RadioGroupContextValue> & LabelProps & StylingOverrideProps & Omit<React$2.ComponentPropsWithoutRef<'input'>, 'className' | 'type'>;
461
+ } & Partial<RadioGroupContextValue> & LabelProps$1 & StylingOverrideProps & Omit<React$2.ComponentPropsWithoutRef<'input'>, 'className' | 'type'>;
458
462
  /**
459
463
  * A presentational radio button component. You will typically use this component within a RadioGroup component.
460
464
  */
@@ -1324,7 +1328,7 @@ declare const Link: <As extends React$2.ElementType = "a">(props: {
1324
1328
  } & RoutedLinkProps & StylingOverrideProps & Omit<React$2.PropsWithoutRef<React$2.ComponentProps<As>>, "className"> & React$2.RefAttributes<unknown>) => React$2.ReactElement;
1325
1329
  //#endregion
1326
1330
  //#region src/components/VerticalNavigation/VerticalNavigation.d.ts
1327
- interface VerticalNavigationProps extends React$2.HTMLAttributes<HTMLElement>, StylingOverrideProps {
1331
+ type VerticalNavigationProps = React$2.HTMLAttributes<HTMLElement> & StylingOverrideProps & {
1328
1332
  /**
1329
1333
  * Controlled collapsed state.
1330
1334
  */
@@ -1338,7 +1342,7 @@ interface VerticalNavigationProps extends React$2.HTMLAttributes<HTMLElement>, S
1338
1342
  * @default false
1339
1343
  */
1340
1344
  defaultCollapsed?: boolean;
1341
- }
1345
+ };
1342
1346
  type VerticalNavigationItemBaseProps<As extends React$2.ElementType> = Omit<React$2.ComponentPropsWithoutRef<As>, 'className' | 'as' | 'href' | 'isActive' | 'isDisabled' | 'rightElement' | 'label'> & StylingOverrideProps & {
1343
1347
  /**
1344
1348
  * The component to use for the item. Default is either 'a' or 'button' based on the presence of the href prop.
@@ -1391,19 +1395,19 @@ type VerticalNavigationItemProps<As extends React$2.ElementType> = VerticalNavig
1391
1395
  * Supports icons, active state, and 'subItem' variant for indentation.
1392
1396
  */
1393
1397
  declare const Item: <As extends React$2.ElementType>({ as, icon, label, isActive, href, FORCE__className, isDisabled, onClick, variant, rightElement, ...props }: VerticalNavigationItemProps<As>) => React$2.JSX.Element;
1394
- interface VerticalNavigationCollapseProps extends React$2.ButtonHTMLAttributes<HTMLButtonElement>, StylingOverrideProps {}
1398
+ type VerticalNavigationCollapseProps = React$2.ButtonHTMLAttributes<HTMLButtonElement> & StylingOverrideProps;
1395
1399
  /**
1396
1400
  * A toggle button to collapse/expand the navigation.
1397
1401
  * Should be placed within VerticalNavigation to control its state.
1398
1402
  */
1399
1403
  declare const Collapse$1: ({ FORCE__className, onClick, ...props }: VerticalNavigationCollapseProps) => React$2.JSX.Element;
1400
- interface VerticalNavigationItemListProps extends React$2.HTMLAttributes<HTMLUListElement>, StylingOverrideProps {}
1404
+ type VerticalNavigationItemListProps = React$2.HTMLAttributes<HTMLUListElement> & StylingOverrideProps;
1401
1405
  /**
1402
1406
  * Container for the primary list of navigation items.
1403
1407
  * Renders an unordered list with consistent spacing and layout.
1404
1408
  */
1405
1409
  declare const ItemList: ({ children, FORCE__className, ...props }: VerticalNavigationItemListProps) => React$2.JSX.Element;
1406
- interface VerticalNavigationFooterProps extends React$2.HTMLAttributes<HTMLUListElement>, StylingOverrideProps {}
1410
+ type VerticalNavigationFooterProps = React$2.HTMLAttributes<HTMLUListElement> & StylingOverrideProps;
1407
1411
  /**
1408
1412
  * Secondary container for footer navigation actions such as settings or help.
1409
1413
  */
@@ -1588,7 +1592,7 @@ type SkeletonProps = {
1588
1592
  * (`title={false}` and `paragraph={false}`) children render inside the placeholder while loading.
1589
1593
  */
1590
1594
  children?: React$2.ReactNode;
1591
- } & StylingOverrideProps & Omit<React$2.HTMLAttributes<HTMLSpanElement>, 'children' | 'title' | 'paragraph'>;
1595
+ } & Omit<StylingOverrideProps, 'style'> & Omit<React$2.HTMLAttributes<HTMLSpanElement>, 'children' | 'title' | 'paragraph' | 'className'>;
1592
1596
  declare function Skeleton(props: SkeletonProps): React$2.JSX.Element | null;
1593
1597
  declare namespace Skeleton {
1594
1598
  var displayName: string;
@@ -1610,7 +1614,7 @@ type SkeletonElementProps = {
1610
1614
  size?: SkeletonSize;
1611
1615
  /** Show animation effect. @default false */
1612
1616
  active?: boolean;
1613
- } & StylingOverrideProps & Omit<React$2.HTMLAttributes<HTMLSpanElement>, 'children'>;
1617
+ } & Omit<StylingOverrideProps, 'style'> & Omit<React$2.HTMLAttributes<HTMLSpanElement>, 'children' | 'className' | 'style'>;
1614
1618
  type SkeletonGroupButtonProps = SkeletonElementProps & {
1615
1619
  block?: boolean;
1616
1620
  shape?: 'circle' | 'round' | 'square' | 'default';
@@ -1810,12 +1814,12 @@ type MenuSectionProps = StylingOverrideProps & Omit<React$2.HTMLAttributes<HTMLD
1810
1814
  */
1811
1815
  children?: React$2.ReactNode;
1812
1816
  };
1813
- interface MenuListProps extends StylingOverrideProps, React$2.HTMLAttributes<HTMLDivElement> {
1817
+ type MenuListProps = StylingOverrideProps & React$2.HTMLAttributes<HTMLDivElement> & {
1814
1818
  /**
1815
1819
  * Menu content. Use Menu.Item, Menu.Section, Menu.Header, Menu.Divider.
1816
1820
  */
1817
1821
  children?: React$2.ReactNode;
1818
- }
1822
+ };
1819
1823
  interface MenuSubmenuProps extends StylingOverrideProps {
1820
1824
  /**
1821
1825
  * Label for the parent row (trailing chevron indicates a nested panel).
@@ -2133,4 +2137,102 @@ type CustomTooltipTriggerProps = {
2133
2137
  */
2134
2138
  declare const CustomTooltipTrigger: React$2.ForwardRefExoticComponent<CustomTooltipTriggerProps & React$2.RefAttributes<HTMLElement>>;
2135
2139
  //#endregion
2136
- export { Alert, type AlertProps, Anchor, type AnchorProps, AutocompleteField, type AutocompleteFieldProps, Badge, BadgeLayout, type BadgeProps, Breadcrumb, type BreadcrumbProps, Breadcrumbs, type BreadcrumbsProps, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Card, Checkbox, type CheckboxProps, Collapse, type CollapseProps, CustomTooltipTrigger, type CustomTooltipTriggerProps, DatePickerField, type DatePickerFieldProps, DateRangePickerField, type DateRangePickerFieldPlaceholder, type DateRangePickerFieldProps, Divider, type DividerProps, type DividerType, Drawer, type DrawerPlacement, type DrawerProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, InputRow, type InputRowAddonProps, type InputRowProps, Link, type LinkProps, ListItem, type ListItemProps, Menu, type MenuDividerProps, type MenuHeaderProps, type MenuItemProps, type MenuListProps, type MenuPanelPadding, type MenuProps, type MenuSectionProps, type MenuSubmenuProps, Modal, type ModalProps, NumberField, type NumberFieldProps, Pagination, type PaginationProps, PasswordField, type PasswordFieldProps, Pill, type PillProps, Popover, type PopoverProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, RadioTile, type RadioTileProps, Ribbon, type RibbonProps, type RoutedLinkProps, RouterProvider, SKELETON_SIZE, SKELETON_SIZE_TOKENS, Skeleton, type SkeletonElementProps, SkeletonGroup, type SkeletonGroupButtonProps, type SkeletonGroupInputProps, type SkeletonGroupNodeProps, type SkeletonParagraphProps, type SkeletonProps, type SkeletonSize, type SkeletonTitleProps, Spinner, type SpinnerProps, type StylingOverrideProps, Switch, type SwitchProps, TabNav, type TabNavItemType, type TabNavItemVariant, type TabNavPlacement, type TabNavProps, type TabNavSubItemType, Tag, type TagColor, type TagProps, Text, TextArea, type TextAreaAutoSize, type TextAreaProps, TextField, type TextFieldProps, type TextProps, Toast, type ToastOptions, type ToastPosition, type ToastType, Tooltip, type TooltipProps, TopNav, type TopNavCenterProps, type TopNavEndProps, type TopNavProps, type TopNavStartProps, VerticalNavigation, type VerticalNavigationCollapseProps, type VerticalNavigationFooterProps, type VerticalNavigationItemListProps, type VerticalNavigationItemProps, type VerticalNavigationProps, VisuallyHidden, type VisuallyHiddenProps, submenuPanelClassName, tagColors };
2140
+ //#region src/components/Tree/Tree.d.ts
2141
+ interface TreeItemType {
2142
+ /**
2143
+ * The unique key of the tree item.
2144
+ */
2145
+ key: Key;
2146
+ /**
2147
+ * The label of the tree item.
2148
+ */
2149
+ label: React$2.ReactNode;
2150
+ /**
2151
+ * The children of the tree item.
2152
+ */
2153
+ children?: TreeItemType[];
2154
+ /**
2155
+ * Whether the tree item is disabled.
2156
+ */
2157
+ isDisabled?: boolean;
2158
+ /**
2159
+ * The suffix of the tree item.
2160
+ */
2161
+ suffix?: React$2.ReactNode;
2162
+ /**
2163
+ * The trailing slot of the tree item.
2164
+ */
2165
+ trailingSlot?: React$2.ReactNode;
2166
+ }
2167
+ type TreeProps = StylingOverrideProps & {
2168
+ /**
2169
+ * Defines a string value that labels the current element.
2170
+ */
2171
+ 'aria-label'?: string;
2172
+ /**
2173
+ * Identifies the element (or elements) that labels the current element.
2174
+ */
2175
+ 'aria-labelledby'?: string;
2176
+ /**
2177
+ * Items to render in the tree.
2178
+ */
2179
+ items: TreeItemType[];
2180
+ /**
2181
+ * Handler that is called when a user performs an action on an item.
2182
+ */
2183
+ onAction?: (key: Key) => void;
2184
+ /**
2185
+ * The initial expanded keys when in uncontrolled mode.
2186
+ */
2187
+ defaultExpandedKeys?: Iterable<Key>;
2188
+ /**
2189
+ * The initial selected keys when in uncontrolled mode.
2190
+ */
2191
+ defaultSelectedKeys?: Iterable<Key>;
2192
+ /**
2193
+ * The currently expanded keys when in controlled mode.
2194
+ */
2195
+ expandedKeys?: Iterable<Key>;
2196
+ /**
2197
+ * Handler that is called when the expanded keys change.
2198
+ */
2199
+ onExpandedChange?: (keys: Set<Key>) => void;
2200
+ /**
2201
+ * Callback that is fired when the selection changes.
2202
+ */
2203
+ onSelectionChange?: (keys: Set<Key>) => void;
2204
+ /**
2205
+ * The currently selected keys when in controlled mode.
2206
+ */
2207
+ selectedKeys?: Iterable<Key>;
2208
+ /**
2209
+ * The selection mode of the tree.
2210
+ * @default 'multiple'
2211
+ */
2212
+ selectionMode?: 'none' | 'multiple';
2213
+ };
2214
+ /**
2215
+ * A hierarchical tree with cascading multi-select and Capra ListItem row layout.
2216
+ */
2217
+ declare function Tree({ FORCE__className: classNameOverride, items, selectionMode, defaultSelectedKeys, selectedKeys, onSelectionChange, expandedKeys, defaultExpandedKeys, ...props }: TreeProps): React$2.JSX.Element;
2218
+ //#endregion
2219
+ //#region src/components/input-helpers/Label.d.ts
2220
+ type LabelProps = {
2221
+ /** Text to display in the label. */
2222
+ children?: string;
2223
+ /** Whether the field the label is labeling is required (shows asterisk after label). */
2224
+ required?: boolean;
2225
+ /** Content after the label text. */
2226
+ trailingSlot?: React$2.ReactNode;
2227
+ } & StylingOverrideProps & Omit<React$2.ComponentPropsWithoutRef<'label'>, 'className' | 'style'>;
2228
+ /** Label text and optional required indicator for form fields, aligned with Capra field layouts. */
2229
+ declare const Label: React$2.ForwardRefExoticComponent<{
2230
+ /** Text to display in the label. */
2231
+ children?: string;
2232
+ /** Whether the field the label is labeling is required (shows asterisk after label). */
2233
+ required?: boolean;
2234
+ /** Content after the label text. */
2235
+ trailingSlot?: React$2.ReactNode;
2236
+ } & StylingOverrideProps & Omit<Omit<React$2.DetailedHTMLProps<React$2.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref">, "className" | "style"> & React$2.RefAttributes<HTMLLabelElement>>;
2237
+ //#endregion
2238
+ export { Alert, type AlertProps, Anchor, type AnchorProps, AutocompleteField, type AutocompleteFieldProps, Badge, BadgeLayout, type BadgeProps, Breadcrumb, type BreadcrumbProps, Breadcrumbs, type BreadcrumbsProps, Button, ButtonLink, type ButtonLinkProps, type ButtonProps, Card, Checkbox, type CheckboxProps, Collapse, type CollapseProps, CustomTooltipTrigger, type CustomTooltipTriggerProps, DatePickerField, type DatePickerFieldProps, DateRangePickerField, type DateRangePickerFieldPlaceholder, type DateRangePickerFieldProps, Divider, type DividerProps, type DividerType, Drawer, type DrawerPlacement, type DrawerProps, EmptyState, type EmptyStateProps, IconButton, type IconButtonProps, InputRow, type InputRowAddonProps, type InputRowProps, Label, type LabelProps, Link, type LinkProps, ListItem, type ListItemProps, Menu, type MenuDividerProps, type MenuHeaderProps, type MenuItemProps, type MenuListProps, type MenuPanelPadding, type MenuProps, type MenuSectionProps, type MenuSubmenuProps, Modal, type ModalProps, NumberField, type NumberFieldProps, Pagination, type PaginationProps, PasswordField, type PasswordFieldProps, Pill, type PillProps, Popover, type PopoverProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, RadioTile, type RadioTileProps, Ribbon, type RibbonProps, type RoutedLinkProps, RouterProvider, SKELETON_SIZE, SKELETON_SIZE_TOKENS, Skeleton, type SkeletonElementProps, SkeletonGroup, type SkeletonGroupButtonProps, type SkeletonGroupInputProps, type SkeletonGroupNodeProps, type SkeletonParagraphProps, type SkeletonProps, type SkeletonSize, type SkeletonTitleProps, Spinner, type SpinnerProps, type StylingOverrideProps, Switch, type SwitchProps, TabNav, type TabNavItemType, type TabNavItemVariant, type TabNavPlacement, type TabNavProps, type TabNavSubItemType, Tag, type TagColor, type TagProps, Text, TextArea, type TextAreaAutoSize, type TextAreaProps, TextField, type TextFieldProps, type TextProps, Toast, type ToastOptions, type ToastPosition, type ToastType, Tooltip, type TooltipProps, TopNav, type TopNavCenterProps, type TopNavEndProps, type TopNavProps, type TopNavStartProps, Tree, type TreeItemType, type TreeProps, VerticalNavigation, type VerticalNavigationCollapseProps, type VerticalNavigationFooterProps, type VerticalNavigationItemListProps, type VerticalNavigationItemProps, type VerticalNavigationProps, VisuallyHidden, type VisuallyHiddenProps, submenuPanelClassName, tagColors };