@deque/cauldron-react 7.0.0 → 7.1.0-canary.07abf03d

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.
@@ -7,6 +7,8 @@ export interface CheckboxProps extends InputHTMLAttributes<HTMLInputElement> {
7
7
  customIcon?: React.ReactNode;
8
8
  checkboxRef?: React.ForwardedRef<HTMLInputElement>;
9
9
  indeterminate?: boolean;
10
+ /** When true, the component does not manage its own checked state — it renders what you pass via `checked` and reports interactions through `onChange`. Use when state is managed by a parent component. */
11
+ controlled?: boolean;
10
12
  }
11
13
  declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
12
14
  export default Checkbox;
@@ -12,6 +12,7 @@ export default class TopBar extends React.Component<MenuBarProps, MenuBarState>
12
12
  thin: boolean;
13
13
  hasTrigger: boolean;
14
14
  };
15
+ private menuBarRef;
15
16
  constructor(props: MenuBarProps);
16
17
  componentDidMount(): void;
17
18
  componentWillUnmount(): void;
@@ -1,39 +1,19 @@
1
1
  import React from 'react';
2
- import AriaIsolate from '../../utils/aria-isolate';
3
2
  export interface ToastProps extends React.HTMLAttributes<HTMLDivElement> {
4
3
  type: 'confirmation' | 'caution' | 'error' | 'action-needed' | 'info';
5
- onDismiss: () => void;
4
+ onDismiss?: () => void;
6
5
  dismissText?: string;
7
- toastRef: React.Ref<HTMLDivElement>;
6
+ /**
7
+ * @deprecated Use the forwarded `ref` instead. Will be removed in the next major version.
8
+ */
9
+ toastRef?: React.Ref<HTMLDivElement>;
8
10
  focus?: boolean;
9
11
  show?: boolean;
10
12
  dismissible?: boolean;
11
13
  children: React.ReactNode;
12
14
  }
13
- interface ToastState {
14
- animationClass: string;
15
- isolator?: AriaIsolate;
16
- }
17
15
  /**
18
16
  * The cauldron toast notification component
19
17
  */
20
- export default class Toast extends React.Component<ToastProps, ToastState> {
21
- static defaultProps: {
22
- dismissText: string;
23
- onDismiss: () => void;
24
- toastRef: () => void;
25
- focus: boolean;
26
- show: boolean;
27
- dismissible: boolean;
28
- };
29
- static displayName: string;
30
- private el;
31
- constructor(props: ToastProps);
32
- componentDidMount(): void;
33
- componentDidUpdate(prevProps: ToastProps): void;
34
- componentWillUnmount(): void;
35
- render(): React.JSX.Element;
36
- dismissToast(): void;
37
- showToast(): void;
38
- }
39
- export {};
18
+ declare const Toast: React.ForwardRefExoticComponent<ToastProps & React.RefAttributes<HTMLDivElement>>;
19
+ export default Toast;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { TreeViewNode } from './types';
3
+ declare const TreeViewItem: {
4
+ ({ id, textValue, children }: TreeViewNode): React.JSX.Element;
5
+ displayName: string;
6
+ };
7
+ export default TreeViewItem;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import { Cauldron } from '../../types';
3
+ import { TreeViewNode } from './types';
4
+ export type { TreeViewNode } from './types';
5
+ type TreeViewProps = Cauldron.LabelProps & {
6
+ items: TreeViewNode[];
7
+ onAction?: (key: string) => void;
8
+ selectionMode?: 'none' | 'single' | 'multiple';
9
+ defaultExpandedKeys?: string[];
10
+ className?: string;
11
+ };
12
+ declare const TreeView: React.ForwardRefExoticComponent<TreeViewProps & React.RefAttributes<HTMLDivElement>>;
13
+ export default TreeView;
@@ -0,0 +1,5 @@
1
+ export interface TreeViewNode {
2
+ id: string;
3
+ textValue: string;
4
+ children?: TreeViewNode[];
5
+ }
package/lib/index.d.ts CHANGED
@@ -68,6 +68,7 @@ export { default as SectionHeader } from './components/SectionHeader';
68
68
  export { default as EmptyState } from './components/EmptyState';
69
69
  export { ActionList, ActionListItem, ActionListGroup, ActionListSeparator, ActionListLinkItem } from './components/ActionList';
70
70
  export { ActionMenu } from './components/ActionMenu';
71
+ export { default as TreeView, type TreeViewNode } from './components/TreeView';
71
72
  /**
72
73
  * Helpers / Utils
73
74
  */
package/lib/index.js CHANGED
@@ -16,6 +16,7 @@ var js = require('react-syntax-highlighter/dist/cjs/languages/hljs/javascript');
16
16
  var css = require('react-syntax-highlighter/dist/cjs/languages/hljs/css');
17
17
  var xml = require('react-syntax-highlighter/dist/cjs/languages/hljs/xml');
18
18
  var yaml = require('react-syntax-highlighter/dist/cjs/languages/hljs/yaml');
19
+ var reactAriaComponents = require('react-aria-components');
19
20
 
20
21
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
21
22
 
@@ -671,6 +672,7 @@ var TopBar$1 = /** @class */ (function (_super) {
671
672
  tslib.__extends(TopBar, _super);
672
673
  function TopBar(props) {
673
674
  var _this = _super.call(this, props) || this;
675
+ _this.menuBarRef = React__default["default"].createRef();
674
676
  _this.onResize = function () {
675
677
  var wide = isWide();
676
678
  if (wide === _this.state.wide) {
@@ -719,10 +721,10 @@ var TopBar$1 = /** @class */ (function (_super) {
719
721
  };
720
722
  TopBar.prototype.onKeyDown = function (e) {
721
723
  var key = keyname__default["default"](e.which);
722
- // This is a temporary workaround until have an opportunity to refactor or replace menubar
723
- // see: https://github.com/dequelabs/cauldron/issues/1934
724
- // eslint-disable-next-line react/no-find-dom-node
725
- var menuBarElement = reactDom.findDOMNode(this);
724
+ var menuBarElement = this.menuBarRef.current;
725
+ if (!menuBarElement) {
726
+ return;
727
+ }
726
728
  var menuItems = Array.from(menuBarElement.children);
727
729
  // account for hidden side bar trigger (hamburger)
728
730
  if (this.state.wide && this.props.hasTrigger) {
@@ -749,7 +751,7 @@ var TopBar$1 = /** @class */ (function (_super) {
749
751
  // disabling no-unused-vars to prevent thin/hasTrigger from being passed through to div
750
752
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
751
753
  var _a = this.props, children = _a.children, className = _a.className; _a.thin; _a.hasTrigger; tslib.__rest(_a, ["children", "className", "thin", "hasTrigger"]);
752
- return (React__default["default"].createElement("ul", { role: "menubar", onKeyDown: this.onKeyDown, className: className }, React.Children.map(children, this.renderChild)));
754
+ return (React__default["default"].createElement("ul", { role: "menubar", onKeyDown: this.onKeyDown, className: className, ref: this.menuBarRef }, React.Children.map(children, this.renderChild)));
753
755
  };
754
756
  TopBar.defaultProps = {
755
757
  thin: false,
@@ -1357,6 +1359,7 @@ function useSharedRef(ref) {
1357
1359
  var internalRef = React.useRef();
1358
1360
  React.useEffect(function () {
1359
1361
  setRef(ref, internalRef.current);
1362
+ return function () { return setRef(ref, null); };
1360
1363
  }, [ref]);
1361
1364
  return internalRef;
1362
1365
  }
@@ -2033,10 +2036,17 @@ function Tooltip(_a) {
2033
2036
  fireCustomEvent(false, targetElement);
2034
2037
  }, TIP_HIDE_DELAY);
2035
2038
  }
2039
+ }, [target]);
2040
+ // Cancel any pending hide timeout when the Tooltip unmounts so it
2041
+ // does not fire setShowTooltip on an unmounted component.
2042
+ React.useEffect(function () {
2036
2043
  return function () {
2037
- clearTimeout(hideTimeoutRef.current);
2044
+ if (hideTimeoutRef.current) {
2045
+ clearTimeout(hideTimeoutRef.current);
2046
+ hideTimeoutRef.current = null;
2047
+ }
2038
2048
  };
2039
- }, [target]);
2049
+ }, []);
2040
2050
  React.useEffect(function () {
2041
2051
  if (typeof showProp === 'boolean') {
2042
2052
  setShowTooltip(showProp);
@@ -2213,126 +2223,118 @@ var tabIndexHandler = function (reset, toast) {
2213
2223
  };
2214
2224
 
2215
2225
  /**
2216
- * The cauldron toast notification component
2226
+ * Hook to be used similarly to the React.Component#componentDidMount.
2227
+ * Executes the provided `effect` when `dependencies` change but does not
2228
+ * execute the effect initially (on mount) - only on update.
2229
+ *
2230
+ * @param effect {Function} function to be executed when dependencies update
2231
+ * @param dependencies {Any} any valid dependency argument to React.useEffect
2217
2232
  */
2218
- var Toast = /** @class */ (function (_super) {
2219
- tslib.__extends(Toast, _super);
2220
- function Toast(props) {
2221
- var _this = _super.call(this, props) || this;
2222
- _this.state = {
2223
- animationClass: props.show ? 'FadeIn--flex' : 'is--hidden'
2224
- };
2225
- _this.dismissToast = _this.dismissToast.bind(_this);
2226
- _this.showToast = _this.showToast.bind(_this);
2227
- return _this;
2228
- }
2229
- Toast.prototype.componentDidMount = function () {
2230
- var show = this.props.show;
2231
- if (show) {
2232
- // Timeout because CSS display: none/block and opacity:
2233
- // 0/1 properties cannot be toggled in the same tick
2234
- // see: https://codepen.io/isnerms/pen/eyQaLP
2235
- setTimeout(this.showToast);
2233
+ var useDidUpdate = function (effect, dependencies) {
2234
+ var mounted = React__default["default"].useRef(false);
2235
+ React__default["default"].useEffect(function () {
2236
+ if (!mounted.current) {
2237
+ mounted.current = true;
2238
+ return;
2236
2239
  }
2240
+ effect();
2241
+ }, dependencies);
2242
+ };
2243
+
2244
+ /**
2245
+ * The cauldron toast notification component
2246
+ */
2247
+ var Toast = React.forwardRef(function (_a, ref) {
2248
+ var type = _a.type, children = _a.children, _b = _a.onDismiss, onDismiss = _b === void 0 ? function () {
2249
+ // noop
2250
+ } : _b, _c = _a.dismissText, dismissText = _c === void 0 ? 'Dismiss' : _c, toastRef = _a.toastRef, _d = _a.focus, focus = _d === void 0 ? true : _d, _e = _a.show, show = _e === void 0 ? false : _e, _f = _a.dismissible, dismissible = _f === void 0 ? true : _f, className = _a.className, otherProps = tslib.__rest(_a, ["type", "children", "onDismiss", "dismissText", "toastRef", "focus", "show", "dismissible", "className"]);
2251
+ var elRef = useSharedRef(ref);
2252
+ var isolatorRef = React.useRef(null);
2253
+ var timeoutsRef = React.useRef(new Set());
2254
+ var _g = tslib.__read(React.useState(show ? 'FadeIn--flex' : 'is--hidden'), 2), animationClass = _g[0], setAnimationClass = _g[1];
2255
+ // Backwards-compat: propagate to the deprecated toastRef prop as well
2256
+ React.useEffect(function () {
2257
+ var _a;
2258
+ if (!toastRef)
2259
+ return;
2260
+ setRef(toastRef, (_a = elRef.current) !== null && _a !== void 0 ? _a : null);
2261
+ return function () { return setRef(toastRef, null); };
2262
+ }, [toastRef]);
2263
+ // Timeout because CSS display: none/block and opacity:
2264
+ // 0/1 properties cannot be toggled in the same tick
2265
+ // see: https://codepen.io/isnerms/pen/eyQaLP
2266
+ var scheduleNextTick = function (fn) {
2267
+ var id = setTimeout(function () {
2268
+ timeoutsRef.current.delete(id);
2269
+ fn();
2270
+ });
2271
+ timeoutsRef.current.add(id);
2237
2272
  };
2238
- Toast.prototype.componentDidUpdate = function (prevProps) {
2239
- var _this = this;
2240
- var show = this.props.show;
2241
- if (prevProps.show !== show) {
2242
- if (show) {
2243
- this.setState({ animationClass: 'FadeIn--flex' }, function () {
2244
- setTimeout(_this.showToast);
2245
- });
2246
- }
2247
- else {
2248
- this.dismissToast();
2249
- }
2273
+ var showToast = React.useCallback(function () {
2274
+ setAnimationClass('FadeIn--flex FadeIn');
2275
+ if (type === 'action-needed' && elRef.current) {
2276
+ var isolator = new AriaIsolate(elRef.current);
2277
+ tabIndexHandler(false, elRef.current);
2278
+ isolatorRef.current = isolator;
2279
+ isolator.activate();
2250
2280
  }
2251
- };
2252
- Toast.prototype.componentWillUnmount = function () {
2253
- var isolator = this.state.isolator;
2254
- isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
2255
- };
2256
- Toast.prototype.render = function () {
2257
- var _this = this;
2258
- var animationClass = this.state.animationClass;
2259
- var _a = this.props, type = _a.type, children = _a.children;
2260
- // prevent `onDismiss` from being passed-through to DOM
2261
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2262
- _a.onDismiss; var dismissText = _a.dismissText, toastRef = _a.toastRef, focus = _a.focus, show = _a.show, dismissible = _a.dismissible, className = _a.className, otherProps = tslib.__rest(_a, ["type", "children", "onDismiss", "dismissText", "toastRef", "focus", "show", "dismissible", "className"]);
2263
- var scrim = type === 'action-needed' && show ? (React__default["default"].createElement("div", { className: "Scrim--light Scrim--show Scrim--fade-in" })) : null;
2264
- var defaultProps = {
2265
- tabIndex: -1,
2266
- className: classNames__default["default"]('Toast', "Toast--".concat(typeMap[type].className), animationClass, { 'Toast--non-dismissible': !dismissible }, className)
2267
- };
2268
- if (!focus) {
2269
- defaultProps.role = 'alert';
2281
+ if (elRef.current && !!focus) {
2282
+ elRef.current.focus();
2270
2283
  }
2271
- return (React__default["default"].createElement(React__default["default"].Fragment, null,
2272
- React__default["default"].createElement("div", tslib.__assign({ ref: function (el) {
2273
- _this.el = el;
2274
- setRef(toastRef, el);
2275
- } }, defaultProps, otherProps),
2276
- React__default["default"].createElement("div", { className: "Toast__message" },
2277
- React__default["default"].createElement(Icon, { type: typeMap[type].icon }),
2278
- React__default["default"].createElement("div", { className: "Toast__message-content" }, children)),
2279
- type !== 'action-needed' && dismissible && (React__default["default"].createElement("button", { type: "button", className: 'Toast__dismiss', "aria-label": dismissText, onClick: this.dismissToast },
2280
- React__default["default"].createElement(Icon, { type: "close" })))),
2281
- scrim));
2282
- };
2283
- Toast.prototype.dismissToast = function () {
2284
- var _this = this;
2285
- if (!this.el) {
2284
+ }, [type, focus]);
2285
+ var dismissToast = React.useCallback(function () {
2286
+ if (!elRef.current) {
2286
2287
  return;
2287
2288
  }
2288
- var _a = this.props, onDismiss = _a.onDismiss, type = _a.type;
2289
- var isolator = this.state.isolator;
2290
- this.setState({
2291
- animationClass: 'FadeIn--flex'
2292
- }, function () {
2293
- // Timeout because CSS display: none/block and opacity:
2294
- // 0/1 properties cannot be toggled in the same tick
2295
- // see: https://codepen.io/isnerms/pen/eyQaLP
2296
- setTimeout(function () {
2297
- if (type === 'action-needed') {
2298
- tabIndexHandler(true, _this.el);
2299
- isolator === null || isolator === void 0 ? void 0 : isolator.deactivate();
2300
- }
2301
- _this.setState({ animationClass: 'is--hidden' }, onDismiss);
2302
- });
2303
- });
2304
- };
2305
- Toast.prototype.showToast = function () {
2306
- var _this = this;
2307
- var _a = this.props, type = _a.type, focus = _a.focus;
2308
- this.setState({
2309
- animationClass: 'FadeIn--flex FadeIn'
2310
- }, function () {
2289
+ setAnimationClass('FadeIn--flex');
2290
+ scheduleNextTick(function () {
2291
+ var _a;
2311
2292
  if (type === 'action-needed') {
2312
- var isolator = new AriaIsolate(_this.el);
2313
- tabIndexHandler(false, _this.el);
2314
- _this.setState({ isolator: isolator });
2315
- isolator.activate();
2316
- }
2317
- if (_this.el && !!focus) {
2318
- // focus the toast
2319
- _this.el.focus();
2293
+ tabIndexHandler(true, elRef.current);
2294
+ (_a = isolatorRef.current) === null || _a === void 0 ? void 0 : _a.deactivate();
2320
2295
  }
2296
+ setAnimationClass('is--hidden');
2297
+ onDismiss();
2321
2298
  });
2299
+ }, [type, onDismiss]);
2300
+ React.useEffect(function () {
2301
+ if (show) {
2302
+ scheduleNextTick(showToast);
2303
+ }
2304
+ return function () {
2305
+ var _a;
2306
+ timeoutsRef.current.forEach(clearTimeout);
2307
+ timeoutsRef.current.clear();
2308
+ (_a = isolatorRef.current) === null || _a === void 0 ? void 0 : _a.deactivate();
2309
+ };
2310
+ }, []);
2311
+ useDidUpdate(function () {
2312
+ if (show) {
2313
+ setAnimationClass('FadeIn--flex');
2314
+ scheduleNextTick(showToast);
2315
+ }
2316
+ else {
2317
+ dismissToast();
2318
+ }
2319
+ }, [show]);
2320
+ var scrim = type === 'action-needed' && show ? (React__default["default"].createElement("div", { className: "Scrim--light Scrim--show Scrim--fade-in" })) : null;
2321
+ var defaultProps = {
2322
+ tabIndex: -1,
2323
+ className: classNames__default["default"]('Toast', "Toast--".concat(typeMap[type].className), animationClass, { 'Toast--non-dismissible': !dismissible }, className)
2322
2324
  };
2323
- Toast.defaultProps = {
2324
- dismissText: 'Dismiss',
2325
- // eslint-disable-next-line @typescript-eslint/no-empty-function
2326
- onDismiss: function () { },
2327
- // eslint-disable-next-line @typescript-eslint/no-empty-function
2328
- toastRef: function () { },
2329
- focus: true,
2330
- show: false,
2331
- dismissible: true
2332
- };
2333
- Toast.displayName = 'Toast';
2334
- return Toast;
2335
- }(React__default["default"].Component));
2325
+ if (!focus) {
2326
+ defaultProps.role = 'alert';
2327
+ }
2328
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
2329
+ React__default["default"].createElement("div", tslib.__assign({ ref: elRef }, defaultProps, otherProps),
2330
+ React__default["default"].createElement("div", { className: "Toast__message" },
2331
+ React__default["default"].createElement(Icon, { type: typeMap[type].icon }),
2332
+ React__default["default"].createElement("div", { className: "Toast__message-content" }, children)),
2333
+ type !== 'action-needed' && dismissible && (React__default["default"].createElement("button", { type: "button", className: "Toast__dismiss", "aria-label": dismissText, onClick: dismissToast },
2334
+ React__default["default"].createElement(Icon, { type: "close" })))),
2335
+ scrim));
2336
+ });
2337
+ Toast.displayName = 'Toast';
2336
2338
 
2337
2339
  var Link = React.forwardRef(function (_a, ref) {
2338
2340
  var children = _a.children, linkRef = _a.linkRef, className = _a.className, variant = _a.variant, thin = _a.thin, other = tslib.__rest(_a, ["children", "linkRef", "className", "variant", "thin"]);
@@ -2599,10 +2601,10 @@ var RadioCardGroup = function (_a) {
2599
2601
  RadioCardGroup.displayName = 'RadioCardGroup';
2600
2602
 
2601
2603
  var Checkbox = React.forwardRef(function (_a, ref) {
2602
- var id = _a.id, label = _a.label, labelDescription = _a.labelDescription, error = _a.error, checkboxRef = _a.checkboxRef, className = _a.className, onChange = _a.onChange, onFocus = _a.onFocus, onBlur = _a.onBlur, ariaDescribedby = _a["aria-describedby"], _b = _a.disabled, disabled = _b === void 0 ? false : _b, _c = _a.checked, checked = _c === void 0 ? false : _c, _d = _a.indeterminate, indeterminate = _d === void 0 ? false : _d; _a.children; var other = tslib.__rest(_a, ["id", "label", "labelDescription", "error", "checkboxRef", "className", "onChange", "onFocus", "onBlur", 'aria-describedby', "disabled", "checked", "indeterminate", "children"]);
2603
- var _e = tslib.__read(React.useState(checked), 2), isChecked = _e[0], setIsChecked = _e[1];
2604
- var _f = tslib.__read(React.useState(indeterminate), 2), isIndeterminate = _f[0], setIsIndeterminate = _f[1];
2605
- var _g = tslib.__read(React.useState(false), 2), focused = _g[0], setFocused = _g[1];
2604
+ var id = _a.id, label = _a.label, labelDescription = _a.labelDescription, error = _a.error, checkboxRef = _a.checkboxRef, className = _a.className, onChange = _a.onChange, _b = _a.controlled, controlled = _b === void 0 ? false : _b, onFocus = _a.onFocus, onBlur = _a.onBlur, ariaDescribedby = _a["aria-describedby"], _c = _a.disabled, disabled = _c === void 0 ? false : _c, _d = _a.checked, checked = _d === void 0 ? false : _d, _e = _a.indeterminate, indeterminate = _e === void 0 ? false : _e; _a.children; var other = tslib.__rest(_a, ["id", "label", "labelDescription", "error", "checkboxRef", "className", "onChange", "controlled", "onFocus", "onBlur", 'aria-describedby', "disabled", "checked", "indeterminate", "children"]);
2605
+ var _f = tslib.__read(React.useState(checked), 2), isChecked = _f[0], setIsChecked = _f[1];
2606
+ var _g = tslib.__read(React.useState(indeterminate), 2), isIndeterminate = _g[0], setIsIndeterminate = _g[1];
2607
+ var _h = tslib.__read(React.useState(false), 2), focused = _h[0], setFocused = _h[1];
2606
2608
  var checkRef = React.useRef(null);
2607
2609
  React.useEffect(function () {
2608
2610
  setIsChecked(checked);
@@ -2614,12 +2616,12 @@ var Checkbox = React.forwardRef(function (_a, ref) {
2614
2616
  if (typeof refProp === 'function') {
2615
2617
  refProp(checkRef.current);
2616
2618
  }
2617
- var _h = React.useMemo(function () {
2619
+ var _j = React.useMemo(function () {
2618
2620
  return {
2619
2621
  labelDescriptionId: nextId__default["default"](),
2620
2622
  errorId: nextId__default["default"]()
2621
2623
  };
2622
- }, []), errorId = _h.errorId, labelDescriptionId = _h.labelDescriptionId;
2624
+ }, []), errorId = _j.errorId, labelDescriptionId = _j.labelDescriptionId;
2623
2625
  var ariaDescribedbyId = ariaDescribedby;
2624
2626
  if (error) {
2625
2627
  ariaDescribedbyId = addIdRef(ariaDescribedbyId, errorId);
@@ -2658,7 +2660,9 @@ var Checkbox = React.forwardRef(function (_a, ref) {
2658
2660
  if (isIndeterminate) {
2659
2661
  setIsIndeterminate(false);
2660
2662
  }
2661
- setIsChecked(e.target.checked);
2663
+ if (!controlled) {
2664
+ setIsChecked(e.target.checked);
2665
+ }
2662
2666
  if (onChange) {
2663
2667
  onChange(e);
2664
2668
  }
@@ -3231,25 +3235,6 @@ var Tab = React__default["default"].forwardRef(function (_a, ref) {
3231
3235
  });
3232
3236
  Tab.displayName = 'Tab';
3233
3237
 
3234
- /**
3235
- * Hook to be used similarly to the React.Component#componentDidMount.
3236
- * Executes the provided `effect` when `dependencies` change but does not
3237
- * execute the effect initially (on mount) - only on update.
3238
- *
3239
- * @param effect {Function} function to be executed when dependencies update
3240
- * @param dependencies {Any} any valid dependency argument to React.useEffect
3241
- */
3242
- var useDidUpdate = function (effect, dependencies) {
3243
- var mounted = React__default["default"].useRef(false);
3244
- React__default["default"].useEffect(function () {
3245
- if (!mounted.current) {
3246
- mounted.current = true;
3247
- return;
3248
- }
3249
- effect();
3250
- }, dependencies);
3251
- };
3252
-
3253
3238
  var Tabs = function (_a) {
3254
3239
  var children = _a.children, thin = _a.thin, _b = _a.orientation, orientation = _b === void 0 ? 'horizontal' : _b, _c = _a.initialActiveIndex, initialActiveIndex = _c === void 0 ? 0 : _c, className = _a.className, onChange = _a.onChange, labelProp = tslib.__rest(_a, ["children", "thin", "orientation", "initialActiveIndex", "className", "onChange"]);
3255
3240
  var _d = tslib.__read(React.useState(initialActiveIndex), 2), activeIndex = _d[0], setActiveIndex = _d[1];
@@ -5425,6 +5410,57 @@ var ActionMenu = React.forwardRef(function (_a, ref) {
5425
5410
  });
5426
5411
  ActionMenu.displayName = 'ActionMenu';
5427
5412
 
5413
+ var TreeViewItem = function (_a) {
5414
+ var id = _a.id, textValue = _a.textValue, children = _a.children;
5415
+ var checkboxId = React.useMemo(function () { return nextId__default["default"]('tree-view-item-'); }, []);
5416
+ return (React__default["default"].createElement(reactAriaComponents.TreeItem, { id: id, textValue: textValue, className: "TreeView__item" },
5417
+ React__default["default"].createElement(reactAriaComponents.TreeItemContent, null, function (_a) {
5418
+ var selectionMode = _a.selectionMode, isSelected = _a.isSelected;
5419
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
5420
+ React__default["default"].createElement(reactAriaComponents.Button, { slot: "chevron", className: "TreeView__chevron" },
5421
+ React__default["default"].createElement(Icon, { type: "chevron-right" })),
5422
+ selectionMode !== 'none' ? (React__default["default"].createElement(Checkbox, { id: checkboxId, label: textValue, checked: isSelected, controlled: true, tabIndex: -1 })) : (React__default["default"].createElement(React__default["default"].Fragment, null, textValue))));
5423
+ }),
5424
+ children && children.length > 0 && (React__default["default"].createElement(reactAriaComponents.Collection, null, children.map(function (child) { return (React__default["default"].createElement(TreeViewItem, tslib.__assign({ key: child.id }, child))); })))));
5425
+ };
5426
+ TreeViewItem.displayName = 'TreeViewItem';
5427
+
5428
+ function collectAllKeys(nodes) {
5429
+ return nodes.flatMap(function (node) { return tslib.__spreadArray([
5430
+ node.id
5431
+ ], tslib.__read((node.children ? collectAllKeys(node.children) : [])), false); });
5432
+ }
5433
+ var TreeView = React.forwardRef(function (_a, ref) {
5434
+ var items = _a.items, onAction = _a.onAction, _b = _a.selectionMode, selectionMode = _b === void 0 ? 'none' : _b, defaultExpandedKeys = _a.defaultExpandedKeys, className = _a.className, other = tslib.__rest(_a, ["items", "onAction", "selectionMode", "defaultExpandedKeys", "className"]);
5435
+ var _c = tslib.__read(React.useState(new Set()), 2), selectedKeys = _c[0], setSelectedKeys = _c[1];
5436
+ var handleAction = function (key) {
5437
+ setSelectedKeys(function (prev) {
5438
+ var prevSet = prev === 'all' ? new Set(collectAllKeys(items)) : new Set(prev);
5439
+ var next = new Set(prevSet);
5440
+ if (next.has(key)) {
5441
+ next.delete(key);
5442
+ }
5443
+ else {
5444
+ if (selectionMode === 'single') {
5445
+ next.clear();
5446
+ }
5447
+ next.add(key);
5448
+ }
5449
+ return next;
5450
+ });
5451
+ onAction === null || onAction === void 0 ? void 0 : onAction(key);
5452
+ };
5453
+ var actionProps = onAction
5454
+ ? {
5455
+ onAction: handleAction,
5456
+ selectedKeys: selectedKeys,
5457
+ onSelectionChange: setSelectedKeys
5458
+ }
5459
+ : {};
5460
+ return (React__default["default"].createElement(reactAriaComponents.Tree, tslib.__assign({ ref: ref, className: classNames__default["default"]('TreeView', className), selectionMode: selectionMode, defaultExpandedKeys: defaultExpandedKeys }, actionProps, other), items.map(function (item) { return (React__default["default"].createElement(TreeViewItem, tslib.__assign({ key: item.id }, item))); })));
5461
+ });
5462
+ TreeView.displayName = 'TreeView';
5463
+
5428
5464
  var LIGHT_THEME_CLASS = 'cauldron--theme-light';
5429
5465
  var DARK_THEME_CLASS = 'cauldron--theme-dark';
5430
5466
  var ThemeContext = React.createContext({
@@ -5620,6 +5656,7 @@ exports.TopBar = TopBar;
5620
5656
  exports.TopBarItem = MenuItem;
5621
5657
  exports.TopBarMenu = TopBarMenu;
5622
5658
  exports.TopBarTrigger = TopBarTrigger;
5659
+ exports.TreeView = TreeView;
5623
5660
  exports.TwoColumnPanel = TwoColumnPanel;
5624
5661
  exports.Workspace = Workspace;
5625
5662
  exports.focusableSelector = focusableSelector;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "7.0.0",
3
+ "version": "7.1.0-canary.07abf03d",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",
@@ -20,13 +20,17 @@
20
20
  "build:css": "postcss --output=lib/cauldron.css src/index.css",
21
21
  "dev": "concurrently 'yarn build:css --watch' 'rollup -c --watch'",
22
22
  "prepublishOnly": "NODE_ENV=production yarn build",
23
- "test": "jest --maxWorkers=1 --coverage"
23
+ "test": "jest --maxWorkers=1 --coverage",
24
+ "figma:parse": "figma connect parse",
25
+ "figma:publish": "figma connect publish",
26
+ "figma:publish:dry-run": "figma connect publish --dry-run"
24
27
  },
25
28
  "dependencies": {
26
29
  "@floating-ui/react-dom": "^2.1.2",
27
30
  "classnames": "^2.2.6",
28
31
  "focusable": "^2.3.0",
29
32
  "keyname": "^0.1.0",
33
+ "react-aria-components": "^1.13.0",
30
34
  "react-id-generator": "^3.0.1",
31
35
  "react-syntax-highlighter": "^16.0.1",
32
36
  "tslib": "^2.4.0"
@@ -37,6 +41,7 @@
37
41
  "@babel/preset-env": "^7.22.10",
38
42
  "@babel/preset-react": "^7.22.5",
39
43
  "@babel/preset-typescript": "^7.22.5",
44
+ "@figma/code-connect": "^1.4.4",
40
45
  "@rollup/plugin-commonjs": "^14.0.0",
41
46
  "@rollup/plugin-dynamic-import-vars": "^1.4.2",
42
47
  "@rollup/plugin-typescript": "^11.1.2",