@itwin/itwinui-react 2.6.0 → 2.7.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 (46) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/cjs/core/Badge/Badge.d.ts +1 -1
  3. package/cjs/core/Badge/Badge.js +14 -15
  4. package/cjs/core/Carousel/Carousel.js +3 -2
  5. package/cjs/core/DatePicker/DatePicker.d.ts +5 -0
  6. package/cjs/core/DatePicker/DatePicker.js +26 -7
  7. package/cjs/core/Slider/Thumb.js +2 -4
  8. package/cjs/core/Tabs/Tabs.js +3 -1
  9. package/cjs/core/Tile/Tile.d.ts +24 -2
  10. package/cjs/core/Tile/Tile.js +85 -50
  11. package/cjs/core/ToggleSwitch/ToggleSwitch.d.ts +11 -31
  12. package/cjs/core/ToggleSwitch/ToggleSwitch.js +8 -1
  13. package/cjs/core/index.d.ts +2 -2
  14. package/cjs/core/index.js +3 -1
  15. package/cjs/core/utils/components/LinkAction.d.ts +30 -0
  16. package/cjs/core/utils/components/LinkAction.js +44 -0
  17. package/cjs/core/utils/components/index.d.ts +1 -0
  18. package/cjs/core/utils/components/index.js +1 -0
  19. package/cjs/core/utils/hooks/index.d.ts +1 -0
  20. package/cjs/core/utils/hooks/index.js +1 -0
  21. package/cjs/core/utils/hooks/useIsClient.d.ts +1 -0
  22. package/cjs/core/utils/hooks/useIsClient.js +19 -0
  23. package/cjs/core/utils/hooks/useTheme.js +5 -0
  24. package/esm/core/Badge/Badge.d.ts +1 -1
  25. package/esm/core/Badge/Badge.js +14 -15
  26. package/esm/core/Carousel/Carousel.js +3 -2
  27. package/esm/core/DatePicker/DatePicker.d.ts +5 -0
  28. package/esm/core/DatePicker/DatePicker.js +26 -7
  29. package/esm/core/Slider/Thumb.js +2 -4
  30. package/esm/core/Tabs/Tabs.js +4 -2
  31. package/esm/core/Tile/Tile.d.ts +24 -2
  32. package/esm/core/Tile/Tile.js +84 -49
  33. package/esm/core/ToggleSwitch/ToggleSwitch.d.ts +11 -31
  34. package/esm/core/ToggleSwitch/ToggleSwitch.js +8 -1
  35. package/esm/core/index.d.ts +2 -2
  36. package/esm/core/index.js +1 -1
  37. package/esm/core/utils/components/LinkAction.d.ts +30 -0
  38. package/esm/core/utils/components/LinkAction.js +38 -0
  39. package/esm/core/utils/components/index.d.ts +1 -0
  40. package/esm/core/utils/components/index.js +1 -0
  41. package/esm/core/utils/hooks/index.d.ts +1 -0
  42. package/esm/core/utils/hooks/index.js +1 -0
  43. package/esm/core/utils/hooks/useIsClient.d.ts +1 -0
  44. package/esm/core/utils/hooks/useIsClient.js +12 -0
  45. package/esm/core/utils/hooks/useTheme.js +5 -0
  46. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bea577e2: Updated the visuals for status colors in Badge.
8
+ - c581e9ed: Added `LinkBox` and `LinkAction`components to improve components with action accessibility.
9
+
10
+ Usage:
11
+
12
+ ```js
13
+ <LinkBox>
14
+ <LinkAction href='/new-page'>Link to click</LinkAction>
15
+ </LinkBox>
16
+ ```
17
+
18
+ - c581e9ed: Added `Tile.Action` to take advantage of these new a11y components in Tile.
19
+
20
+ Usage:
21
+
22
+ ```js
23
+ <Tile
24
+ name={
25
+ <Tile.Action as='button' onClick={() => {/* Do things */}>
26
+ Tile name that is also a button
27
+ </Tile.Action>
28
+ }
29
+ />
30
+ ```
31
+
32
+ - 61f44293: Added new `isDateDisabled` prop to DatePicker. Accepts a function which takes a date and returns a boolean to indicate whether that date is not selectable.
33
+
34
+ ### Patch Changes
35
+
36
+ - 198d6a95: Remove the ability to set icon prop for ToggleSwitch when size is set to small
37
+ - c5cfa4c6: Fixed an issue with incremental migration where adding a close button to v2 Toaster was breaking v1 styles for the whole page.
38
+ - a1f235d0: Fixed Carousel showing warnings in React 16 when using arrow keys.
39
+ - c9dee6f5: Fixed an issue where Slider's tooltip was still visible after unmounting the component.
40
+ - 775933e3: The DOM order of Tile content has changed so that the name comes before the thumbnail region. This improves accessibility without affecting visuals.
41
+ - 028d4cd7: Updated actionable tile to have a more prominent hover effect.
42
+ - 341449ca: Fixes an issue where stripe width for borderless and pill tabs was rendering an incorrect length upon first visiting the page.
43
+ - Updated dependencies
44
+ - @itwin/itwinui-css@1.8.0
45
+
3
46
  ## 2.6.0
4
47
 
5
48
  ### Minor Changes
@@ -10,7 +10,7 @@ export declare type BadgeProps = {
10
10
  *
11
11
  * If not specified, a default neutral background will be used.
12
12
  */
13
- backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
13
+ backgroundColor?: 'primary' | 'informational' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
14
14
  /**
15
15
  * Badge label.
16
16
  * Always gets converted to uppercase, and truncated if too long.
@@ -19,18 +19,14 @@ const getBadgeColorValue = (color) => {
19
19
  if (!color) {
20
20
  return '';
21
21
  }
22
- switch (color) {
23
- case 'primary':
24
- return '#A5D7F5';
25
- case 'positive':
26
- return '#C3E1AF';
27
- case 'negative':
28
- return '#EFA9A9';
29
- case 'warning':
30
- return '#F9D7AB';
31
- default:
32
- return (0, utils_1.isSoftBackground)(color) ? utils_1.SoftBackgrounds[color] : color;
33
- }
22
+ return (0, utils_1.isSoftBackground)(color) ? utils_1.SoftBackgrounds[color] : color;
23
+ };
24
+ /**
25
+ * Helper function that returns one of the preset badge status values.
26
+ */
27
+ const getStatusValue = (color) => {
28
+ const statuses = ['positive', 'negative', 'warning', 'informational'];
29
+ return color && statuses.includes(color) ? color : undefined;
34
30
  };
35
31
  /**
36
32
  * A colorful visual indicator for categorizing items.
@@ -42,13 +38,16 @@ const getBadgeColorValue = (color) => {
42
38
  const Badge = (props) => {
43
39
  const { backgroundColor, style, className, children, ...rest } = props;
44
40
  (0, utils_1.useTheme)();
45
- const _style = backgroundColor
41
+ // choosing 'primary' status should result in data-iui-status equaling 'informational'
42
+ const reducedBackgroundColor = backgroundColor === 'primary' ? 'informational' : backgroundColor;
43
+ const statusValue = getStatusValue(reducedBackgroundColor);
44
+ const _style = reducedBackgroundColor && !statusValue
46
45
  ? {
47
- '--iui-badge-background-color': getBadgeColorValue(backgroundColor),
46
+ '--iui-badge-background-color': getBadgeColorValue(reducedBackgroundColor),
48
47
  ...style,
49
48
  }
50
49
  : { ...style };
51
- return (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-badge', className), style: _style, ...rest }, children));
50
+ return (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-badge', className), style: _style, "data-iui-status": statusValue, ...rest }, children));
52
51
  };
53
52
  exports.Badge = Badge;
54
53
  exports.default = exports.Badge;
@@ -66,8 +66,9 @@ exports.Carousel = Object.assign(react_1.default.forwardRef((props, ref) => {
66
66
  if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
67
67
  return;
68
68
  }
69
- if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
70
- setKeysPressed((old) => ({ ...old, [event.key]: true }));
69
+ const key = event.key;
70
+ if (key === 'ArrowLeft' || key === 'ArrowRight') {
71
+ setKeysPressed((old) => ({ ...old, [key]: true }));
71
72
  }
72
73
  };
73
74
  const handleKeyUp = (event) => {
@@ -61,6 +61,11 @@ export declare type DatePickerProps = {
61
61
  * @default false
62
62
  */
63
63
  showYearSelection?: boolean;
64
+ /**
65
+ * Will disable dates for which this function returns true.
66
+ * Disabled dates cannot be selected.
67
+ */
68
+ isDateDisabled?: (date: Date) => boolean;
64
69
  } & DateRangePickerProps & Omit<TimePickerProps, 'date' | 'onChange' | 'setFocusHour'>;
65
70
  /**
66
71
  * Date picker component
@@ -130,7 +130,7 @@ exports.generateLocalizedStrings = generateLocalizedStrings;
130
130
  */
131
131
  const DatePicker = (props) => {
132
132
  var _a, _b, _c, _d, _e, _f, _g, _h;
133
- const { date, onChange, localizedNames, className, style, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, ...rest } = props;
133
+ const { date, onChange, localizedNames, className, style, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, isDateDisabled, ...rest } = props;
134
134
  (0, utils_1.useTheme)();
135
135
  const monthNames = (_a = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.months) !== null && _a !== void 0 ? _a : defaultMonths;
136
136
  const shortDays = (_b = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.shortDays) !== null && _b !== void 0 ? _b : defaultShortDays;
@@ -267,6 +267,10 @@ const DatePicker = (props) => {
267
267
  }
268
268
  }
269
269
  };
270
+ const isPreviousMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex, 0));
271
+ const isNextMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex + 1, 1));
272
+ const isPreviousYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear - 1, 11, 31));
273
+ const isNextYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear + 1, 0, 1));
270
274
  const handleCalendarKeyDown = (event) => {
271
275
  if (!focusedDay) {
272
276
  return;
@@ -276,6 +280,9 @@ const DatePicker = (props) => {
276
280
  case 'ArrowDown':
277
281
  adjustedFocusedDay.setDate(focusedDay.getDate() + 7);
278
282
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
283
+ if (isNextMonthDisabled) {
284
+ return;
285
+ }
279
286
  handleMoveToNextMonth();
280
287
  }
281
288
  setFocusedDay(adjustedFocusedDay);
@@ -285,6 +292,9 @@ const DatePicker = (props) => {
285
292
  case 'ArrowUp':
286
293
  adjustedFocusedDay.setDate(focusedDay.getDate() - 7);
287
294
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
295
+ if (isPreviousMonthDisabled) {
296
+ return;
297
+ }
288
298
  handleMoveToPreviousMonth();
289
299
  }
290
300
  setFocusedDay(adjustedFocusedDay);
@@ -294,6 +304,9 @@ const DatePicker = (props) => {
294
304
  case 'ArrowLeft':
295
305
  adjustedFocusedDay.setDate(focusedDay.getDate() - 1);
296
306
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
307
+ if (isPreviousMonthDisabled) {
308
+ return;
309
+ }
297
310
  handleMoveToPreviousMonth();
298
311
  }
299
312
  setFocusedDay(adjustedFocusedDay);
@@ -303,6 +316,9 @@ const DatePicker = (props) => {
303
316
  case 'ArrowRight':
304
317
  adjustedFocusedDay.setDate(focusedDay.getDate() + 1);
305
318
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
319
+ if (isNextMonthDisabled) {
320
+ return;
321
+ }
306
322
  handleMoveToNextMonth();
307
323
  }
308
324
  setFocusedDay(adjustedFocusedDay);
@@ -312,7 +328,9 @@ const DatePicker = (props) => {
312
328
  case 'Enter':
313
329
  case ' ':
314
330
  case 'Spacebar':
315
- onDayClick(focusedDay);
331
+ if (!(isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(focusedDay))) {
332
+ onDayClick(focusedDay);
333
+ }
316
334
  event.preventDefault();
317
335
  break;
318
336
  }
@@ -347,23 +365,24 @@ const DatePicker = (props) => {
347
365
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-date-picker', className), style: style, ...rest },
348
366
  react_1.default.createElement("div", null,
349
367
  react_1.default.createElement("div", { className: 'iui-calendar-month-year' },
350
- showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small' },
368
+ showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small', disabled: isPreviousYearDisabled },
351
369
  react_1.default.createElement(utils_1.SvgChevronLeftDouble, null))),
352
- react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small' },
370
+ react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small', disabled: isPreviousMonthDisabled },
353
371
  react_1.default.createElement(utils_1.SvgChevronLeft, null)),
354
372
  react_1.default.createElement("span", { "aria-live": 'polite' },
355
373
  react_1.default.createElement("span", { className: 'iui-calendar-month', title: monthNames[displayedMonthIndex] }, monthNames[displayedMonthIndex]),
356
374
  "\u00A0",
357
375
  displayedYear),
358
- react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small' },
376
+ react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small', disabled: isNextMonthDisabled },
359
377
  react_1.default.createElement(utils_1.SvgChevronRight, null)),
360
- showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small' },
378
+ showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small', disabled: isNextYearDisabled },
361
379
  react_1.default.createElement(utils_1.SvgChevronRightDouble, null)))),
362
380
  react_1.default.createElement("div", { className: 'iui-calendar-weekdays' }, shortDays.map((day, index) => (react_1.default.createElement("div", { key: day, title: longDays[index] }, day)))),
363
381
  react_1.default.createElement("div", { onKeyDown: handleCalendarKeyDown, role: 'listbox' }, weeks.map((weekDays, weekIndex) => {
364
382
  return (react_1.default.createElement("div", { key: `week-${displayedMonthIndex}-${weekIndex}`, className: 'iui-calendar-week' }, weekDays.map((weekDay, dayIndex) => {
365
383
  const dateValue = weekDay.getDate();
366
- return (react_1.default.createElement("div", { key: `day-${displayedMonthIndex}-${dayIndex}`, className: getDayClass(weekDay), onClick: () => onDayClick(weekDay), role: 'option', tabIndex: isSameDay(weekDay, focusedDay) ? 0 : -1, ref: (element) => isSameDay(weekDay, focusedDay) &&
384
+ const isDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(weekDay);
385
+ return (react_1.default.createElement("div", { key: `day-${displayedMonthIndex}-${dayIndex}`, className: getDayClass(weekDay), onClick: () => !isDisabled && onDayClick(weekDay), role: 'option', tabIndex: isSameDay(weekDay, focusedDay) ? 0 : -1, "aria-disabled": isDisabled ? 'true' : undefined, ref: (element) => isSameDay(weekDay, focusedDay) &&
367
386
  needFocus.current &&
368
387
  (element === null || element === void 0 ? void 0 : element.focus()) }, dateValue));
369
388
  })));
@@ -46,8 +46,6 @@ const Thumb = (props) => {
46
46
  const handlePointerDownOnThumb = react_1.default.useCallback(() => {
47
47
  !disabled && onThumbActivated(index);
48
48
  }, [disabled, index, onThumbActivated]);
49
- const [hasFocus, setHasFocus] = react_1.default.useState(false);
50
- const [isHovered, setIsHovered] = react_1.default.useState(false);
51
49
  const adjustedValue = react_1.default.useMemo(() => {
52
50
  if (value < sliderMin) {
53
51
  return sliderMin;
@@ -64,12 +62,12 @@ const Thumb = (props) => {
64
62
  return (100.0 * (adjustedValue - sliderMin)) / (sliderMax - sliderMin);
65
63
  }, [adjustedValue, sliderMax, sliderMin]);
66
64
  const { style, className, ...rest } = thumbProps || {};
67
- return (react_1.default.createElement(Tooltip_1.Tooltip, { visible: isActive || hasFocus || isHovered, placement: 'top', ...tooltipProps },
65
+ return (react_1.default.createElement(Tooltip_1.Tooltip, { placement: 'top', trigger: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.visible) == null ? 'mouseenter click focus' : undefined, ...tooltipProps },
68
66
  react_1.default.createElement("div", { ...rest, "data-index": index, ref: thumbRef, style: {
69
67
  ...style,
70
68
  ...(orientation === 'horizontal'
71
69
  ? { left: `${lowPercent}%` }
72
70
  : { bottom: `${lowPercent}%` }),
73
- }, className: (0, classnames_1.default)('iui-slider-thumb', { 'iui-active': isActive }, className), role: 'slider', tabIndex: disabled ? undefined : 0, "aria-valuemin": minVal, "aria-valuenow": value, "aria-valuemax": maxVal, "aria-disabled": disabled, onPointerDown: handlePointerDownOnThumb, onKeyDown: (event) => handleOnKeyboardEvent(event, false), onKeyUp: (event) => handleOnKeyboardEvent(event, true), onFocus: () => setHasFocus(true), onBlur: () => setHasFocus(false), onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) })));
71
+ }, className: (0, classnames_1.default)('iui-slider-thumb', { 'iui-active': isActive }, className), role: 'slider', tabIndex: disabled ? undefined : 0, "aria-valuemin": minVal, "aria-valuenow": value, "aria-valuemax": maxVal, "aria-disabled": disabled, onPointerDown: handlePointerDownOnThumb, onKeyDown: (event) => handleOnKeyboardEvent(event, false), onKeyUp: (event) => handleOnKeyboardEvent(event, true) })));
74
72
  };
75
73
  exports.Thumb = Thumb;
@@ -50,6 +50,7 @@ const Tabs = (props) => {
50
50
  }
51
51
  const { labels, activeIndex, onTabSelected, focusActivationMode = 'auto', type = 'default', color = 'blue', orientation = 'horizontal', tabsClassName, contentClassName, wrapperClassName, children, ...rest } = props;
52
52
  (0, utils_1.useTheme)();
53
+ const isClient = (0, utils_1.useIsClient)();
53
54
  const tablistRef = react_1.default.useRef(null);
54
55
  const [tablistSizeRef, tabsWidth] = (0, utils_1.useContainerWidth)(type !== 'default');
55
56
  const refs = (0, utils_1.useMergedRefs)(tablistRef, tablistSizeRef);
@@ -161,7 +162,8 @@ const Tabs = (props) => {
161
162
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tabs-wrapper', `iui-${orientation}`, wrapperClassName), style: stripeProperties },
162
163
  react_1.default.createElement("ul", { className: (0, classnames_1.default)('iui-tabs', `iui-${type}`, {
163
164
  'iui-green': color === 'green',
164
- 'iui-animated': type !== 'default',
165
+ 'iui-animated': type !== 'default' && isClient,
166
+ 'iui-not-animated': type !== 'default' && !isClient,
165
167
  'iui-large': hasSublabel,
166
168
  }, tabsClassName), role: 'tablist', ref: refs, onKeyDown: onKeyDown, ...rest }, labels.map((label, index) => {
167
169
  const onClick = () => {
@@ -1,5 +1,16 @@
1
1
  import React from 'react';
2
+ import { PolymorphicComponentProps } from '../utils';
2
3
  import '@itwin/itwinui-css/css/tile.css';
4
+ declare type TileActionOwnProps = {};
5
+ /**
6
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
7
+ * Renders `a` element by default.
8
+ * @example
9
+ * <Tile
10
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
11
+ * />
12
+ */
13
+ export declare const TileAction: (props: PolymorphicComponentProps<'a', TileActionOwnProps>) => JSX.Element;
3
14
  export declare type TileProps = {
4
15
  /**
5
16
  * Name or title of the tile.
@@ -102,7 +113,8 @@ export declare type TileProps = {
102
113
  * @default false
103
114
  */
104
115
  isDisabled?: boolean;
105
- } & React.ComponentPropsWithoutRef<'div'>;
116
+ onClick?: React.MouseEventHandler<HTMLElement>;
117
+ } & Omit<React.ComponentPropsWithoutRef<'div'>, 'onClick'>;
106
118
  /**
107
119
  * Tile component that displays content and actions in a card-like format.
108
120
  * @example
@@ -120,5 +132,15 @@ export declare type TileProps = {
120
132
  * isNew={false}
121
133
  * />
122
134
  */
123
- export declare const Tile: (props: TileProps) => JSX.Element;
135
+ export declare const Tile: ((props: TileProps) => JSX.Element) & {
136
+ /**
137
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
138
+ * Renders `a` element by default.
139
+ * @example
140
+ * <Tile
141
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
142
+ * />
143
+ */
144
+ Action: (props: PolymorphicComponentProps<'a', TileActionOwnProps>) => JSX.Element;
145
+ };
124
146
  export default Tile;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Tile = void 0;
6
+ exports.Tile = exports.TileAction = void 0;
7
7
  /*---------------------------------------------------------------------------------------------
8
8
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
9
9
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -15,6 +15,27 @@ require("@itwin/itwinui-css/css/tile.css");
15
15
  const DropdownMenu_1 = require("../DropdownMenu");
16
16
  const Buttons_1 = require("../Buttons");
17
17
  const ProgressIndicators_1 = require("../ProgressIndicators");
18
+ const TileContext = react_1.default.createContext(undefined);
19
+ /**
20
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
21
+ * Renders `a` element by default.
22
+ * @example
23
+ * <Tile
24
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
25
+ * />
26
+ */
27
+ const TileAction = (props) => {
28
+ var _a, _b, _c;
29
+ const tileContext = (0, utils_1.useSafeContext)(TileContext);
30
+ const supportsHas = (_c = (_b = (_a = (0, utils_1.getWindow)()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, 'selector(:has(+ *))');
31
+ react_1.default.useEffect(() => {
32
+ if (!supportsHas) {
33
+ tileContext.setActionable(true);
34
+ }
35
+ }, [supportsHas, tileContext]);
36
+ return react_1.default.createElement(utils_1.LinkAction, { ...props });
37
+ };
38
+ exports.TileAction = TileAction;
18
39
  /**
19
40
  * Tile component that displays content and actions in a card-like format.
20
41
  * @example
@@ -32,59 +53,73 @@ const ProgressIndicators_1 = require("../ProgressIndicators");
32
53
  * isNew={false}
33
54
  * />
34
55
  */
35
- const Tile = (props) => {
36
- const { className, name, description, metadata, thumbnail, buttons, leftIcon, rightIcon, badge, isNew, isSelected, moreOptions, variant = 'default', children, isActionable, status, isLoading = false, isDisabled = false, ...rest } = props;
56
+ exports.Tile = Object.assign((props) => {
57
+ const { className, name, description, metadata, thumbnail, buttons, leftIcon, rightIcon, badge, isNew, isSelected, moreOptions, variant = 'default', children, isActionable: isActionableProp, status, isLoading = false, isDisabled = false, onClick, ...rest } = props;
37
58
  (0, utils_1.useTheme)();
38
59
  const [isMenuVisible, setIsMenuVisible] = react_1.default.useState(false);
39
60
  const showMenu = react_1.default.useCallback(() => setIsMenuVisible(true), []);
40
61
  const hideMenu = react_1.default.useCallback(() => setIsMenuVisible(false), []);
41
- return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tile', {
42
- 'iui-folder': variant === 'folder',
43
- 'iui-new': isNew,
44
- 'iui-selected': isSelected,
45
- 'iui-actionable': isActionable,
46
- [`iui-${status}`]: !!status,
47
- 'iui-loading': isLoading,
48
- }, className), "aria-disabled": isDisabled, tabIndex: isActionable && !isDisabled ? 0 : undefined, ...rest },
49
- thumbnail && (react_1.default.createElement("div", { className: 'iui-tile-thumbnail' },
50
- typeof thumbnail === 'string' ? (react_1.default.createElement("div", { className: 'iui-tile-thumbnail-picture', style: { backgroundImage: `url(${thumbnail})` } })) : thumbnail && thumbnail.type === 'img' ? (react_1.default.cloneElement(thumbnail, {
51
- className: 'iui-tile-thumbnail-picture',
52
- })) : react_1.default.isValidElement(thumbnail) ? (react_1.default.cloneElement(thumbnail, {
53
- className: (0, classnames_1.default)('iui-thumbnail-icon', thumbnail.props.className),
54
- })) : (thumbnail),
55
- leftIcon &&
56
- react_1.default.cloneElement(leftIcon, {
57
- className: 'iui-tile-thumbnail-type-indicator',
58
- 'data-iui-size': 'small',
59
- }),
60
- rightIcon &&
61
- react_1.default.cloneElement(rightIcon, {
62
- className: 'iui-tile-thumbnail-quick-action',
63
- 'data-iui-size': 'small',
64
- }),
65
- badge && (react_1.default.createElement("div", { className: 'iui-tile-thumbnail-badge-container' }, badge)))),
66
- react_1.default.createElement("div", { className: 'iui-tile-content' },
67
- react_1.default.createElement("div", { className: 'iui-tile-name' },
68
- react_1.default.createElement(TitleIcon, { isLoading: isLoading, isSelected: isSelected, isNew: isNew, status: status }),
69
- react_1.default.createElement("span", { className: 'iui-tile-name-label' }, name)),
70
- description != undefined && (react_1.default.createElement("div", { className: 'iui-tile-description' }, description)),
71
- metadata != undefined && (react_1.default.createElement("div", { className: 'iui-tile-metadata' }, metadata)),
72
- moreOptions && (react_1.default.createElement(DropdownMenu_1.DropdownMenu, { onShow: showMenu, onHide: hideMenu, menuItems: (close) => moreOptions.map((option) => react_1.default.cloneElement(option, {
73
- onClick: (value) => {
74
- var _a, _b;
75
- close();
76
- (_b = (_a = option.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, value);
77
- },
78
- })) },
79
- react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tile-more-options', {
80
- 'iui-visible': isMenuVisible,
81
- }) },
82
- react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', size: 'small', "aria-label": 'More options' },
83
- react_1.default.createElement(utils_1.SvgMore, null))))),
84
- children),
85
- buttons && react_1.default.createElement("div", { className: 'iui-tile-buttons' }, buttons)));
86
- };
87
- exports.Tile = Tile;
62
+ const [localActionable, setLocalActionable] = react_1.default.useState(isActionableProp);
63
+ const isActionable = isActionableProp !== null && isActionableProp !== void 0 ? isActionableProp : localActionable;
64
+ const tileName = (react_1.default.createElement("div", { className: 'iui-tile-name' },
65
+ react_1.default.createElement(TitleIcon, { isLoading: isLoading, isSelected: isSelected, isNew: isNew, status: status }),
66
+ react_1.default.createElement("span", { className: 'iui-tile-name-label' }, isActionable && onClick ? (react_1.default.createElement(utils_1.LinkAction, { as: 'button', onClick: !isDisabled ? onClick : undefined, "aria-disabled": isDisabled }, name)) : (name))));
67
+ return (react_1.default.createElement(TileContext.Provider, { value: { setActionable: setLocalActionable } },
68
+ react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tile', {
69
+ 'iui-folder': variant === 'folder',
70
+ 'iui-new': isNew,
71
+ 'iui-selected': isSelected,
72
+ 'iui-actionable': isActionable,
73
+ [`iui-${status}`]: !!status,
74
+ 'iui-loading': isLoading,
75
+ }, className), "aria-disabled": isDisabled, ...rest },
76
+ variant !== 'folder' ? tileName : null,
77
+ thumbnail && (react_1.default.createElement("div", { className: 'iui-tile-thumbnail' },
78
+ typeof thumbnail === 'string' ? (react_1.default.createElement("div", { className: 'iui-tile-thumbnail-picture', style: { backgroundImage: `url(${thumbnail})` } })) : thumbnail && thumbnail.type === 'img' ? (react_1.default.cloneElement(thumbnail, {
79
+ className: 'iui-tile-thumbnail-picture',
80
+ })) : react_1.default.isValidElement(thumbnail) ? (react_1.default.cloneElement(thumbnail, {
81
+ className: (0, classnames_1.default)('iui-thumbnail-icon', thumbnail.props.className),
82
+ })) : (thumbnail),
83
+ leftIcon &&
84
+ react_1.default.cloneElement(leftIcon, {
85
+ className: 'iui-tile-thumbnail-type-indicator',
86
+ 'data-iui-size': 'small',
87
+ }),
88
+ rightIcon &&
89
+ react_1.default.cloneElement(rightIcon, {
90
+ className: 'iui-tile-thumbnail-quick-action',
91
+ 'data-iui-size': 'small',
92
+ }),
93
+ badge && (react_1.default.createElement("div", { className: 'iui-tile-thumbnail-badge-container' }, badge)))),
94
+ react_1.default.createElement("div", { className: 'iui-tile-content' },
95
+ variant === 'folder' ? tileName : null,
96
+ description != undefined && (react_1.default.createElement("div", { className: 'iui-tile-description' }, description)),
97
+ metadata != undefined && (react_1.default.createElement("div", { className: 'iui-tile-metadata' }, metadata)),
98
+ moreOptions && (react_1.default.createElement(DropdownMenu_1.DropdownMenu, { onShow: showMenu, onHide: hideMenu, menuItems: (close) => moreOptions.map((option) => react_1.default.cloneElement(option, {
99
+ onClick: (value) => {
100
+ var _a, _b;
101
+ close();
102
+ (_b = (_a = option.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, value);
103
+ },
104
+ })) },
105
+ react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tile-more-options', {
106
+ 'iui-visible': isMenuVisible,
107
+ }) },
108
+ react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', size: 'small', "aria-label": 'More options' },
109
+ react_1.default.createElement(utils_1.SvgMore, null))))),
110
+ children),
111
+ buttons && react_1.default.createElement("div", { className: 'iui-tile-buttons' }, buttons))));
112
+ }, {
113
+ /**
114
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
115
+ * Renders `a` element by default.
116
+ * @example
117
+ * <Tile
118
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
119
+ * />
120
+ */
121
+ Action: exports.TileAction,
122
+ });
88
123
  const TitleIcon = ({ isLoading = false, isSelected = false, isNew = false, status, }) => {
89
124
  const StatusIcon = !!status && utils_1.StatusIconMap[status];
90
125
  if (isLoading) {
@@ -15,16 +15,20 @@ export declare type ToggleSwitchProps = {
15
15
  * @default false
16
16
  */
17
17
  setFocus?: boolean;
18
- /**
19
- * Icon inside the toggle switch. Shown only when toggle is checked.
20
- */
21
- icon?: JSX.Element;
18
+ } & ({
22
19
  /**
23
20
  * Size of the toggle switch.
24
21
  * @default 'default'
25
22
  */
26
- size?: 'default' | 'small';
27
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'>;
23
+ size?: 'default';
24
+ /**
25
+ * Icon inside the toggle switch. Shown only when toggle is checked and size is not small.
26
+ */
27
+ icon?: JSX.Element;
28
+ } | {
29
+ size: 'small';
30
+ icon?: never;
31
+ }) & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'>;
28
32
  /**
29
33
  * A switch for turning on and off.
30
34
  * @example
@@ -43,29 +47,5 @@ export declare type ToggleSwitchProps = {
43
47
  * <caption>Toggle with icon</caption>
44
48
  * <ToggleSwitch label='With icon toggle' icon={<svg viewBox='0 0 16 16'><path d='M1 1v14h14V1H1zm13 1.7v10.6L8.7 8 14 2.7zM8 7.3L2.7 2h10.6L8 7.3zm-.7.7L2 13.3V2.7L7.3 8zm.7.7l5.3 5.3H2.7L8 8.7z' /></svg>} />
45
49
  */
46
- export declare const ToggleSwitch: React.ForwardRefExoticComponent<{
47
- /**
48
- * Label for the toggle switch.
49
- */
50
- label?: React.ReactNode;
51
- /**
52
- * Position of the label.
53
- * @default 'right'
54
- */
55
- labelPosition?: "right" | "left" | undefined;
56
- /**
57
- * Set focus on toggle.
58
- * @default false
59
- */
60
- setFocus?: boolean | undefined;
61
- /**
62
- * Icon inside the toggle switch. Shown only when toggle is checked.
63
- */
64
- icon?: JSX.Element | undefined;
65
- /**
66
- * Size of the toggle switch.
67
- * @default 'default'
68
- */
69
- size?: "small" | "default" | undefined;
70
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & React.RefAttributes<HTMLInputElement>>;
50
+ export declare const ToggleSwitch: React.ForwardRefExoticComponent<ToggleSwitchProps & React.RefAttributes<HTMLInputElement>>;
71
51
  export default ToggleSwitch;
@@ -31,7 +31,13 @@ require("@itwin/itwinui-css/css/toggle-switch.css");
31
31
  * <ToggleSwitch label='With icon toggle' icon={<svg viewBox='0 0 16 16'><path d='M1 1v14h14V1H1zm13 1.7v10.6L8.7 8 14 2.7zM8 7.3L2.7 2h10.6L8 7.3zm-.7.7L2 13.3V2.7L7.3 8zm.7.7l5.3 5.3H2.7L8 8.7z' /></svg>} />
32
32
  */
33
33
  exports.ToggleSwitch = react_1.default.forwardRef((props, ref) => {
34
- const { disabled = false, labelPosition = 'right', icon, label, setFocus = false, className, style, size = 'default', ...rest } = props;
34
+ let icon;
35
+ if (props.size !== 'small') {
36
+ icon = props.icon;
37
+ props = { ...props };
38
+ delete props.icon;
39
+ }
40
+ const { disabled = false, labelPosition = 'right', label, setFocus = false, className, style, size = 'default', ...rest } = props;
35
41
  (0, utils_1.useTheme)();
36
42
  const inputElementRef = react_1.default.useRef(null);
37
43
  const refs = (0, utils_1.useMergedRefs)(inputElementRef, ref);
@@ -48,6 +54,7 @@ exports.ToggleSwitch = react_1.default.forwardRef((props, ref) => {
48
54
  }, className), "data-iui-size": size, style: style },
49
55
  react_1.default.createElement("input", { className: 'iui-toggle-switch', type: 'checkbox', role: 'switch', disabled: disabled, ref: refs, ...rest }),
50
56
  icon &&
57
+ size !== 'small' &&
51
58
  react_1.default.cloneElement(icon, {
52
59
  className: (0, classnames_1.default)('iui-toggle-switch-icon', icon.props.className),
53
60
  'aria-hidden': true,
@@ -104,5 +104,5 @@ export { Anchor, Body, Headline, Leading, Small, Subheading, Title, Blockquote,
104
104
  export type { AnchorProps, BodyProps, HeadlineProps, LeadingProps, SmallProps, SubheadingProps, TitleProps, BlockquoteProps, CodeProps, KbdProps, TextProps, } from './Typography';
105
105
  export { Wizard, Stepper, WorkflowDiagram } from './Stepper';
106
106
  export type { WizardProps, StepProperties, WizardType, WizardLocalization, StepperProps, StepperLocalization, WorkflowDiagramProps, } from './Stepper';
107
- export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, Flex, } from './utils';
108
- export type { ThemeType, MiddleTextTruncationProps, IconProps, FlexProps, FlexItemProps, FlexSpacerProps, } from './utils';
107
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, LinkBox, LinkAction, Icon, Flex, } from './utils';
108
+ export type { ThemeType, MiddleTextTruncationProps, IconProps, FlexProps, FlexItemProps, FlexSpacerProps, LinkBoxProps, LinkActionProps, } from './utils';
package/cjs/core/index.js CHANGED
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Input = exports.InformationPanelContent = exports.InformationPanelBody = exports.InformationPanelHeader = exports.InformationPanelWrapper = exports.InformationPanel = exports.HorizontalTabs = exports.Tab = exports.Tabs = exports.VerticalTabs = exports.HeaderLogo = exports.HeaderButton = exports.HeaderBreadcrumbs = exports.Header = exports.defaultFooterElements = exports.Footer = exports.FileEmptyCard = exports.FileUploadCard = exports.FileUploadTemplate = exports.FileUpload = exports.Fieldset = exports.ExpandableBlock = exports.NonIdealState = exports.ErrorPage = exports.DropdownMenu = exports.Dialog = exports.generateLocalizedStrings = exports.DatePicker = exports.ComboBox = exports.ColorPalette = exports.ColorInputPanel = exports.ColorBuilder = exports.ColorSwatch = exports.ColorPicker = exports.Checkbox = exports.Carousel = exports.ButtonGroup = exports.SplitButton = exports.IdeasButton = exports.IconButton = exports.DropdownButton = exports.Button = exports.Breadcrumbs = exports.Badge = exports.Backdrop = exports.UserIconGroup = exports.AvatarGroup = exports.UserIcon = exports.Avatar = exports.Alert = void 0;
7
7
  exports.TreeNodeExpander = exports.TreeNode = exports.Tree = exports.Tooltip = exports.ToggleSwitch = exports.ThemeProvider = exports.toaster = exports.TimePicker = exports.Tile = exports.Textarea = exports.TagContainer = exports.Tag = exports.SelectionColumn = exports.ExpanderColumn = exports.ActionColumn = exports.TablePaginator = exports.EditableCell = exports.DefaultCell = exports.FilterButtonBar = exports.BaseFilter = exports.tableFilters = exports.Table = exports.Surface = exports.StatusMessage = exports.Slider = exports.SkipToContentLink = exports.SidenavSubmenuHeader = exports.SidenavSubmenu = exports.SidenavButton = exports.SideNavigation = exports.Select = exports.RadioTileGroup = exports.RadioTile = exports.Radio = exports.ProgressRadial = exports.ProgressLinear = exports.NotificationMarker = exports.ModalContent = exports.ModalButtonBar = exports.Modal = exports.MenuItemSkeleton = exports.MenuExtraContent = exports.MenuDivider = exports.MenuItem = exports.Menu = exports.LabeledTextarea = exports.LabeledSelect = exports.InputGroup = exports.LabeledInput = exports.Label = void 0;
8
- exports.Flex = exports.Icon = exports.MiddleTextTruncation = exports.ColorValue = exports.useTheme = exports.getUserColor = exports.WorkflowDiagram = exports.Stepper = exports.Wizard = exports.Text = exports.KbdKeys = exports.Kbd = exports.Code = exports.Blockquote = exports.Title = exports.Subheading = exports.Small = exports.Leading = exports.Headline = exports.Body = exports.Anchor = void 0;
8
+ exports.Flex = exports.Icon = exports.LinkAction = exports.LinkBox = exports.MiddleTextTruncation = exports.ColorValue = exports.useTheme = exports.getUserColor = exports.WorkflowDiagram = exports.Stepper = exports.Wizard = exports.Text = exports.KbdKeys = exports.Kbd = exports.Code = exports.Blockquote = exports.Title = exports.Subheading = exports.Small = exports.Leading = exports.Headline = exports.Body = exports.Anchor = void 0;
9
9
  /*---------------------------------------------------------------------------------------------
10
10
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
11
11
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -183,5 +183,7 @@ Object.defineProperty(exports, "getUserColor", { enumerable: true, get: function
183
183
  Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return utils_1.useTheme; } });
184
184
  Object.defineProperty(exports, "ColorValue", { enumerable: true, get: function () { return utils_1.ColorValue; } });
185
185
  Object.defineProperty(exports, "MiddleTextTruncation", { enumerable: true, get: function () { return utils_1.MiddleTextTruncation; } });
186
+ Object.defineProperty(exports, "LinkBox", { enumerable: true, get: function () { return utils_1.LinkBox; } });
187
+ Object.defineProperty(exports, "LinkAction", { enumerable: true, get: function () { return utils_1.LinkAction; } });
186
188
  Object.defineProperty(exports, "Icon", { enumerable: true, get: function () { return utils_1.Icon; } });
187
189
  Object.defineProperty(exports, "Flex", { enumerable: true, get: function () { return utils_1.Flex; } });