@deque/cauldron-react 6.2.1-canary.2d4991a8 → 6.2.1-canary.3e6e4cd8

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,7 @@ interface SearchFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, '
7
7
  onChange?: (value: string, e: ChangeEvent<HTMLInputElement>) => void;
8
8
  hideLabel?: boolean;
9
9
  isForm?: boolean;
10
+ trailingChildren?: React.ReactNode;
10
11
  }
11
12
  declare const SearchField: React.ForwardRefExoticComponent<SearchFieldProps & React.RefAttributes<HTMLInputElement>>;
12
13
  export default SearchField;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { type TooltipProps } from '../Tooltip';
3
+ interface TextEllipsisProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ children: string;
5
+ maxLines?: number;
6
+ as?: React.ElementType;
7
+ refProp?: string;
8
+ tooltipProps?: Omit<TooltipProps, 'target' | 'association'>;
9
+ }
10
+ declare const TextEllipsis: React.ForwardRefExoticComponent<TextEllipsisProps & React.RefAttributes<HTMLElement>>;
11
+ export default TextEllipsis;
@@ -5,7 +5,7 @@ export interface TooltipProps extends React.HTMLAttributes<HTMLDivElement> {
5
5
  className?: string;
6
6
  target: React.RefObject<HTMLElement> | HTMLElement;
7
7
  variant?: 'text' | 'info' | 'big';
8
- association?: 'aria-labelledby' | 'aria-describedby';
8
+ association?: 'aria-labelledby' | 'aria-describedby' | 'none';
9
9
  show?: boolean | undefined;
10
10
  placement?: Placement;
11
11
  portal?: React.RefObject<HTMLElement> | HTMLElement;
package/lib/index.d.ts CHANGED
@@ -55,6 +55,7 @@ export { default as Listbox, ListboxOption, ListboxGroup } from './components/Li
55
55
  export { default as Combobox, ComboboxOption, ComboboxGroup } from './components/Combobox';
56
56
  export { default as Popover } from './components/Popover';
57
57
  export { default as Timeline, TimelineItem } from './components/Timeline';
58
+ export { default as TextEllipsis } from './components/TextEllipsis';
58
59
  /**
59
60
  * Helpers / Utils
60
61
  */
package/lib/index.js CHANGED
@@ -1601,6 +1601,43 @@ var Button = React.forwardRef(function (_a, ref) {
1601
1601
  });
1602
1602
  Button.displayName = 'Button';
1603
1603
 
1604
+ /**
1605
+ * Returns a unique set of id refs from the provided string
1606
+ * @param ids - string of id refs
1607
+ */
1608
+ function idRefs(ids) {
1609
+ if (!ids || !ids.trim()) {
1610
+ return new Set();
1611
+ }
1612
+ return new Set(ids.trim().split(/\s+/));
1613
+ }
1614
+ /**
1615
+ * Returns an updated id ref string with the provided id value added
1616
+ * @param ids - string of id refs
1617
+ * @param id - id to add
1618
+ */
1619
+ function addIdRef(ids, id) {
1620
+ return tslib.__spreadArray([], tslib.__read(idRefs(ids).add(id)), false).join(' ');
1621
+ }
1622
+ /**
1623
+ * Returns an updated id ref string with the provided id value removed
1624
+ * @param ids - string of id refs
1625
+ * @param id - id to remove
1626
+ */
1627
+ function removeIdRef(_ids, id) {
1628
+ var ids = idRefs(_ids);
1629
+ ids.delete(id);
1630
+ return tslib.__spreadArray([], tslib.__read(ids), false).join(' ');
1631
+ }
1632
+ /**
1633
+ * Returns if an id ref string contains the provided id value
1634
+ * @param ids - string of id refs
1635
+ * @param id - id to check if it exists in the provided idRef string
1636
+ */
1637
+ function hasIdRef(ids, id) {
1638
+ return idRefs(ids).has(id);
1639
+ }
1640
+
1604
1641
  var TIP_HIDE_DELAY = 100;
1605
1642
  // fires a custom "cauldron:tooltip:show" / "cauldron:tooltip:hide" event
1606
1643
  // to allow projects using cauldron to hook into when a tooltip is shown/hidden
@@ -1622,6 +1659,7 @@ function Tooltip(_a) {
1622
1659
  var _j = tslib.__read(React.useState(null), 2), targetElement = _j[0], setTargetElement = _j[1];
1623
1660
  var _k = tslib.__read(React.useState(null), 2), tooltipElement = _k[0], setTooltipElement = _k[1];
1624
1661
  var _l = tslib.__read(React.useState(null), 2), arrowElement = _l[0], setArrowElement = _l[1];
1662
+ var hasAriaAssociation = association !== 'none';
1625
1663
  var _m = reactPopper.usePopper(targetElement, tooltipElement, {
1626
1664
  placement: initialPlacement,
1627
1665
  modifiers: [
@@ -1723,11 +1761,19 @@ function Tooltip(_a) {
1723
1761
  }, [tooltipElement, show, hide]);
1724
1762
  // Keep the target's id in sync
1725
1763
  React.useEffect(function () {
1726
- var attrText = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute(association);
1727
- if (!(attrText === null || attrText === void 0 ? void 0 : attrText.includes(id || ''))) {
1728
- targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute(association, [id, attrText].filter(Boolean).join(' '));
1764
+ if (hasAriaAssociation) {
1765
+ var idRefs = targetElement === null || targetElement === void 0 ? void 0 : targetElement.getAttribute(association);
1766
+ if (!hasIdRef(idRefs, id)) {
1767
+ targetElement === null || targetElement === void 0 ? void 0 : targetElement.setAttribute(association, addIdRef(idRefs, id));
1768
+ }
1729
1769
  }
1730
- }, [targetElement, id]);
1770
+ return function () {
1771
+ if (targetElement && hasAriaAssociation) {
1772
+ var idRefs = targetElement.getAttribute(association);
1773
+ targetElement.setAttribute(association, removeIdRef(idRefs, id));
1774
+ }
1775
+ };
1776
+ }, [targetElement, id, association]);
1731
1777
  return (React__default["default"].createElement(React__default["default"].Fragment, null, (showTooltip || hideElementOnHidden) && isBrowser()
1732
1778
  ? reactDom.createPortal(React__default["default"].createElement("div", tslib.__assign({ id: id, className: classNames__default["default"]('Tooltip', "Tooltip--".concat(placement), className, {
1733
1779
  TooltipInfo: variant === 'info',
@@ -1998,19 +2044,6 @@ var randomId = function () {
1998
2044
  return "x_".concat(i++, "_").concat(num);
1999
2045
  };
2000
2046
 
2001
- /**
2002
- * Adds an id to a token list attribute if its not already present in the list
2003
- */
2004
- var tokenList = function (id, currentVal) {
2005
- if (currentVal === void 0) { currentVal = ''; }
2006
- var values = currentVal.split(' ');
2007
- if (values.includes(id)) {
2008
- return currentVal;
2009
- }
2010
- values.push(id);
2011
- return values.join(' ').trim();
2012
- };
2013
-
2014
2047
  var Select = React__default["default"].forwardRef(function (_a, ref) {
2015
2048
  var options = _a.options, children = _a.children, disabled = _a.disabled, label = _a.label, id = _a.id, required = _a.required, _b = _a.requiredText, requiredText = _b === void 0 ? 'Required' : _b, error = _a.error, value = _a.value, ariaDescribedby = _a["aria-describedby"], defaultValue = _a.defaultValue, onChange = _a.onChange, rest = tslib.__rest(_a, ["options", "children", "disabled", "label", "id", "required", "requiredText", "error", "value", 'aria-describedby', "defaultValue", "onChange"]);
2016
2049
  if (options && children) {
@@ -2044,7 +2077,7 @@ var Select = React__default["default"].forwardRef(function (_a, ref) {
2044
2077
  dynamicProps.defaultValue = defaultValue;
2045
2078
  }
2046
2079
  if (error) {
2047
- dynamicProps['aria-describedby'] = tokenList(errorId, ariaDescribedby);
2080
+ dynamicProps['aria-describedby'] = addIdRef(ariaDescribedby, errorId);
2048
2081
  }
2049
2082
  // In order to support controlled selects, we
2050
2083
  // have to attach an `onChange` to the select.
@@ -2260,10 +2293,10 @@ var Checkbox = React.forwardRef(function (_a, ref) {
2260
2293
  }, []), errorId = _f.errorId, labelDescriptionId = _f.labelDescriptionId;
2261
2294
  var ariaDescribedbyId = ariaDescribedby;
2262
2295
  if (error) {
2263
- ariaDescribedbyId = tokenList(errorId, ariaDescribedbyId);
2296
+ ariaDescribedbyId = addIdRef(ariaDescribedbyId, errorId);
2264
2297
  }
2265
2298
  if (labelDescription) {
2266
- ariaDescribedbyId = tokenList(labelDescriptionId, ariaDescribedbyId);
2299
+ ariaDescribedbyId = addIdRef(ariaDescribedbyId, labelDescriptionId);
2267
2300
  }
2268
2301
  return (React__default["default"].createElement("div", { className: "Checkbox__wrap" },
2269
2302
  React__default["default"].createElement("div", { className: classNames__default["default"]('Checkbox is--flex-row', className) },
@@ -2349,7 +2382,7 @@ var TextField = /** @class */ (function (_super) {
2349
2382
  var Field = multiline ? 'textarea' : 'input';
2350
2383
  var inputProps = {
2351
2384
  'aria-describedby': error
2352
- ? tokenList(this.errorId, ariaDescribedby)
2385
+ ? addIdRef(ariaDescribedby, this.errorId)
2353
2386
  : ariaDescribedby
2354
2387
  };
2355
2388
  return (React__default["default"].createElement("div", { className: "Field" },
@@ -2403,7 +2436,7 @@ var TextFieldWrapper = React.forwardRef(function (_a, ref) {
2403
2436
  TextFieldWrapper.displayName = 'TextFieldWrapper';
2404
2437
 
2405
2438
  var SearchField = React.forwardRef(function (_a, ref) {
2406
- var label = _a.label, _b = _a.defaultValue, defaultValue = _b === void 0 ? '' : _b, onChange = _a.onChange, _c = _a.hideLabel, hideLabel = _c === void 0 ? false : _c, _d = _a.placeholder, placeholder = _d === void 0 ? 'Search...' : _d, _e = _a.isForm, isForm = _e === void 0 ? true : _e, propId = _a.id, propValue = _a.value, otherProps = tslib.__rest(_a, ["label", "defaultValue", "onChange", "hideLabel", "placeholder", "isForm", "id", "value"]);
2439
+ var label = _a.label, _b = _a.defaultValue, defaultValue = _b === void 0 ? '' : _b, onChange = _a.onChange, _c = _a.hideLabel, hideLabel = _c === void 0 ? false : _c, _d = _a.placeholder, placeholder = _d === void 0 ? 'Search...' : _d, _e = _a.isForm, isForm = _e === void 0 ? true : _e, propId = _a.id, propValue = _a.value, trailingChildren = _a.trailingChildren, otherProps = tslib.__rest(_a, ["label", "defaultValue", "onChange", "hideLabel", "placeholder", "isForm", "id", "value", "trailingChildren"]);
2407
2440
  var isControlled = typeof propValue !== 'undefined';
2408
2441
  var _f = tslib.__read(React.useState(isControlled ? propValue : defaultValue), 2), value = _f[0], setValue = _f[1];
2409
2442
  var _g = tslib.__read(propId ? [propId] : nextId.useId(1, 'search-field'), 1), id = _g[0];
@@ -2419,6 +2452,9 @@ var SearchField = React.forwardRef(function (_a, ref) {
2419
2452
  setValue(newValue);
2420
2453
  };
2421
2454
  var Field = isForm ? 'form' : 'div';
2455
+ if (typeof trailingChildren === 'string') {
2456
+ trailingChildren = React__default["default"].createElement("span", null, trailingChildren);
2457
+ }
2422
2458
  return (React__default["default"].createElement(Field, { role: isForm ? 'search' : undefined, className: "SearchField", "aria-labelledby": isForm ? "".concat(inputId, "-label") : undefined },
2423
2459
  hideLabel ? (React__default["default"].createElement(Offscreen, null,
2424
2460
  React__default["default"].createElement("label", { htmlFor: inputId, id: "".concat(inputId, "-label") }, label))) : (React__default["default"].createElement("label", { className: "Field__label", htmlFor: inputId, id: "".concat(inputId, "-label") }, label)),
@@ -2426,7 +2462,8 @@ var SearchField = React.forwardRef(function (_a, ref) {
2426
2462
  'TextFieldWrapper--disabled': otherProps.disabled
2427
2463
  }) },
2428
2464
  React__default["default"].createElement(Icon, { type: "magnifying-glass", className: "SearchField__search-icon" }),
2429
- React__default["default"].createElement("input", tslib.__assign({ id: inputId, value: value, onChange: handleChange, placeholder: placeholder, ref: ref }, otherProps, { className: classNames__default["default"](otherProps.className, 'Field__text-input'), type: "search" })))));
2465
+ React__default["default"].createElement("input", tslib.__assign({ id: inputId, value: value, onChange: handleChange, placeholder: placeholder, ref: ref }, otherProps, { className: classNames__default["default"](otherProps.className, 'Field__text-input'), type: "search" })),
2466
+ trailingChildren)));
2430
2467
  });
2431
2468
  SearchField.displayName = 'SearchField';
2432
2469
 
@@ -3736,7 +3773,7 @@ var Combobox = React.forwardRef(function (_a, ref) {
3736
3773
  noMatchingOptions));
3737
3774
  var errorId = "".concat(id, "-error");
3738
3775
  var inputProps = tslib.__assign(tslib.__assign({}, props), { 'aria-describedby': error
3739
- ? tokenList(errorId, ariaDescribedby)
3776
+ ? addIdRef(ariaDescribedby, errorId)
3740
3777
  : ariaDescribedby });
3741
3778
  return (React__default["default"].createElement("div", { id: id, className: classNames__default["default"]('Combobox', className), ref: comboboxRef },
3742
3779
  name && React__default["default"].createElement("input", { type: "hidden", name: name, value: formValue }),
@@ -3925,6 +3962,51 @@ function TimelineItem(_a) {
3925
3962
  React__default["default"].createElement("div", { className: "TimelineItem__details" }, children)));
3926
3963
  }
3927
3964
 
3965
+ var TextEllipsis = React__default["default"].forwardRef(function (_a, ref) {
3966
+ var className = _a.className, children = _a.children, maxLines = _a.maxLines, as = _a.as, tooltipProps = _a.tooltipProps, props = tslib.__rest(_a, ["className", "children", "maxLines", "as", "tooltipProps"]);
3967
+ var Element = 'div';
3968
+ var sharedRef = useSharedRef(ref);
3969
+ var _b = tslib.__read(React.useState(false), 2), showTooltip = _b[0], setShowTooltip = _b[1];
3970
+ if (as) {
3971
+ Element = as;
3972
+ }
3973
+ else if (showTooltip) {
3974
+ props = Object.assign({
3975
+ role: 'button',
3976
+ 'aria-disabled': true,
3977
+ tabIndex: 0
3978
+ }, props);
3979
+ }
3980
+ if (typeof maxLines === 'number') {
3981
+ props.style = tslib.__assign({ WebkitLineClamp: maxLines || 2 }, props.style);
3982
+ }
3983
+ React.useEffect(function () {
3984
+ var listener = function () {
3985
+ requestAnimationFrame(function () {
3986
+ var overflowElement = sharedRef.current;
3987
+ if (!overflowElement) {
3988
+ return;
3989
+ }
3990
+ var hasOverflow = typeof maxLines === 'number'
3991
+ ? overflowElement.clientHeight < overflowElement.scrollHeight
3992
+ : overflowElement.clientWidth < overflowElement.scrollWidth;
3993
+ setShowTooltip(hasOverflow);
3994
+ });
3995
+ };
3996
+ var observer = new ResizeObserver(listener);
3997
+ observer.observe(sharedRef.current);
3998
+ return function () {
3999
+ observer === null || observer === void 0 ? void 0 : observer.disconnect();
4000
+ };
4001
+ }, []);
4002
+ return (React__default["default"].createElement(React__default["default"].Fragment, null,
4003
+ React__default["default"].createElement(Element, tslib.__assign({ className: classNames__default["default"]('TextEllipsis', className, {
4004
+ 'TextEllipsis--multiline': !!maxLines
4005
+ }), ref: sharedRef }, props), children),
4006
+ showTooltip && (React__default["default"].createElement(Tooltip, tslib.__assign({ target: sharedRef, association: "none" }, tooltipProps), children))));
4007
+ });
4008
+ TextEllipsis.displayName = 'TextEllipsis';
4009
+
3928
4010
  var LIGHT_THEME_CLASS = 'cauldron--theme-light';
3929
4011
  var DARK_THEME_CLASS = 'cauldron--theme-dark';
3930
4012
  var ThemeContext = React.createContext({
@@ -4082,6 +4164,7 @@ exports.Tabs = Tabs;
4082
4164
  exports.Tag = Tag;
4083
4165
  exports.TagButton = TagButton;
4084
4166
  exports.TagLabel = TagLabel;
4167
+ exports.TextEllipsis = TextEllipsis;
4085
4168
  exports.TextField = TextField;
4086
4169
  exports.ThemeContext = ThemeContext;
4087
4170
  exports.ThemeProvider = ThemeProvider;
@@ -0,0 +1,25 @@
1
+ type IdRefs = string | null | undefined;
2
+ /**
3
+ * Returns a unique set of id refs from the provided string
4
+ * @param ids - string of id refs
5
+ */
6
+ export default function idRefs(ids: IdRefs): Set<string>;
7
+ /**
8
+ * Returns an updated id ref string with the provided id value added
9
+ * @param ids - string of id refs
10
+ * @param id - id to add
11
+ */
12
+ export declare function addIdRef(ids: IdRefs, id: string): string;
13
+ /**
14
+ * Returns an updated id ref string with the provided id value removed
15
+ * @param ids - string of id refs
16
+ * @param id - id to remove
17
+ */
18
+ export declare function removeIdRef(_ids: IdRefs, id: string): string;
19
+ /**
20
+ * Returns if an id ref string contains the provided id value
21
+ * @param ids - string of id refs
22
+ * @param id - id to check if it exists in the provided idRef string
23
+ */
24
+ export declare function hasIdRef(ids: IdRefs, id: string): boolean;
25
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deque/cauldron-react",
3
- "version": "6.2.1-canary.2d4991a8",
3
+ "version": "6.2.1-canary.3e6e4cd8",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Fully accessible react components library for Deque Cauldron",
6
6
  "homepage": "https://cauldron.dequelabs.com/",
@@ -1,2 +0,0 @@
1
- declare function recursivelyRemoveIds(element: React.ReactNode): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>> | import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>[] | null | undefined;
2
- export default recursivelyRemoveIds;
@@ -1,5 +0,0 @@
1
- /**
2
- * Adds an id to a token list attribute if its not already present in the list
3
- */
4
- declare const tokenList: (id: string, currentVal?: string) => string;
5
- export default tokenList;