@itwin/itwinui-react 3.15.4 → 3.16.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 (137) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/DEV-cjs/core/Breadcrumbs/Breadcrumbs.js +2 -2
  3. package/DEV-cjs/core/Checkbox/Checkbox.js +4 -6
  4. package/DEV-cjs/core/ComboBox/ComboBox.js +10 -6
  5. package/DEV-cjs/core/DatePicker/DatePicker.js +9 -1
  6. package/DEV-cjs/core/Dialog/Dialog.js +1 -1
  7. package/DEV-cjs/core/Panels/Panels.js +319 -0
  8. package/DEV-cjs/core/Panels/helpers.js +62 -0
  9. package/DEV-cjs/core/Radio/Radio.js +4 -6
  10. package/DEV-cjs/core/RadioTiles/RadioTileGroup.js +9 -2
  11. package/DEV-cjs/core/Select/SelectTag.js +9 -11
  12. package/DEV-cjs/core/Select/SelectTagContainer.js +2 -2
  13. package/DEV-cjs/core/Stepper/Stepper.js +1 -0
  14. package/DEV-cjs/core/Stepper/StepperStep.js +2 -1
  15. package/DEV-cjs/core/Table/Table.js +64 -47
  16. package/DEV-cjs/core/Table/TablePaginator.js +15 -3
  17. package/DEV-cjs/core/Table/actionHandlers/selectHandler.js +10 -7
  18. package/DEV-cjs/core/Table/columns/selectionColumn.js +6 -1
  19. package/DEV-cjs/core/Tree/Tree.js +1 -0
  20. package/DEV-cjs/index.js +4 -0
  21. package/DEV-cjs/styles.js +1 -1
  22. package/DEV-cjs/utils/components/MiddleTextTruncation.js +22 -4
  23. package/DEV-cjs/utils/components/OverflowContainer.js +170 -27
  24. package/DEV-cjs/utils/hooks/index.js +1 -1
  25. package/DEV-cjs/utils/hooks/useInstance.js +38 -0
  26. package/DEV-esm/core/Breadcrumbs/Breadcrumbs.js +2 -2
  27. package/DEV-esm/core/Checkbox/Checkbox.js +5 -10
  28. package/DEV-esm/core/ComboBox/ComboBox.js +10 -6
  29. package/DEV-esm/core/DatePicker/DatePicker.js +11 -1
  30. package/DEV-esm/core/Dialog/Dialog.js +1 -1
  31. package/DEV-esm/core/Panels/Panels.js +301 -0
  32. package/DEV-esm/core/Panels/helpers.js +42 -0
  33. package/DEV-esm/core/Radio/Radio.js +4 -9
  34. package/DEV-esm/core/RadioTiles/RadioTileGroup.js +8 -2
  35. package/DEV-esm/core/Select/SelectTag.js +9 -11
  36. package/DEV-esm/core/Select/SelectTagContainer.js +2 -2
  37. package/DEV-esm/core/Stepper/Stepper.js +1 -0
  38. package/DEV-esm/core/Stepper/StepperStep.js +2 -1
  39. package/DEV-esm/core/Table/Table.js +61 -47
  40. package/DEV-esm/core/Table/TablePaginator.js +16 -3
  41. package/DEV-esm/core/Table/actionHandlers/selectHandler.js +10 -7
  42. package/DEV-esm/core/Table/columns/selectionColumn.js +6 -1
  43. package/DEV-esm/core/Tree/Tree.js +1 -0
  44. package/DEV-esm/index.js +1 -0
  45. package/DEV-esm/styles.js +1 -1
  46. package/DEV-esm/utils/components/MiddleTextTruncation.js +22 -4
  47. package/DEV-esm/utils/components/OverflowContainer.js +143 -4
  48. package/DEV-esm/utils/hooks/index.js +1 -1
  49. package/DEV-esm/utils/hooks/useInstance.js +18 -0
  50. package/cjs/core/Breadcrumbs/Breadcrumbs.js +2 -2
  51. package/cjs/core/Checkbox/Checkbox.js +4 -6
  52. package/cjs/core/ComboBox/ComboBox.d.ts +13 -0
  53. package/cjs/core/ComboBox/ComboBox.js +10 -6
  54. package/cjs/core/DatePicker/DatePicker.d.ts +2 -2
  55. package/cjs/core/DatePicker/DatePicker.js +2 -1
  56. package/cjs/core/Dialog/Dialog.js +1 -1
  57. package/cjs/core/Dialog/DialogContext.d.ts +6 -2
  58. package/cjs/core/NonIdealState/NonIdealState.d.ts +15 -11
  59. package/cjs/core/Panels/Panels.d.ts +174 -0
  60. package/cjs/core/Panels/Panels.js +312 -0
  61. package/cjs/core/Panels/helpers.d.ts +23 -0
  62. package/cjs/core/Panels/helpers.js +61 -0
  63. package/cjs/core/Radio/Radio.js +4 -6
  64. package/cjs/core/RadioTiles/RadioTileGroup.d.ts +3 -1
  65. package/cjs/core/RadioTiles/RadioTileGroup.js +9 -2
  66. package/cjs/core/Select/SelectTag.d.ts +3 -1
  67. package/cjs/core/Select/SelectTag.js +9 -11
  68. package/cjs/core/Select/SelectTagContainer.js +2 -2
  69. package/cjs/core/Stepper/Stepper.d.ts +4 -0
  70. package/cjs/core/Stepper/Stepper.js +1 -0
  71. package/cjs/core/Stepper/StepperStep.d.ts +4 -0
  72. package/cjs/core/Stepper/StepperStep.js +2 -1
  73. package/cjs/core/Table/Table.d.ts +1 -0
  74. package/cjs/core/Table/Table.js +64 -47
  75. package/cjs/core/Table/TablePaginator.js +15 -3
  76. package/cjs/core/Table/actionHandlers/selectHandler.js +10 -7
  77. package/cjs/core/Table/columns/selectionColumn.js +6 -1
  78. package/cjs/core/Tree/Tree.js +1 -0
  79. package/cjs/index.d.ts +1 -0
  80. package/cjs/index.js +4 -0
  81. package/cjs/styles.js +1 -1
  82. package/cjs/utils/components/MiddleTextTruncation.d.ts +5 -7
  83. package/cjs/utils/components/MiddleTextTruncation.js +22 -4
  84. package/cjs/utils/components/OverflowContainer.d.ts +1 -0
  85. package/cjs/utils/components/OverflowContainer.js +170 -27
  86. package/cjs/utils/hooks/index.d.ts +1 -1
  87. package/cjs/utils/hooks/index.js +1 -1
  88. package/cjs/utils/hooks/useInstance.d.ts +22 -0
  89. package/cjs/utils/hooks/useInstance.js +38 -0
  90. package/esm/core/Breadcrumbs/Breadcrumbs.js +2 -2
  91. package/esm/core/Checkbox/Checkbox.js +5 -10
  92. package/esm/core/ComboBox/ComboBox.d.ts +13 -0
  93. package/esm/core/ComboBox/ComboBox.js +10 -6
  94. package/esm/core/DatePicker/DatePicker.d.ts +2 -2
  95. package/esm/core/DatePicker/DatePicker.js +4 -1
  96. package/esm/core/Dialog/Dialog.js +1 -1
  97. package/esm/core/Dialog/DialogContext.d.ts +6 -2
  98. package/esm/core/NonIdealState/NonIdealState.d.ts +15 -11
  99. package/esm/core/Panels/Panels.d.ts +174 -0
  100. package/esm/core/Panels/Panels.js +294 -0
  101. package/esm/core/Panels/helpers.d.ts +23 -0
  102. package/esm/core/Panels/helpers.js +41 -0
  103. package/esm/core/Radio/Radio.js +4 -9
  104. package/esm/core/RadioTiles/RadioTileGroup.d.ts +3 -1
  105. package/esm/core/RadioTiles/RadioTileGroup.js +8 -2
  106. package/esm/core/Select/SelectTag.d.ts +3 -1
  107. package/esm/core/Select/SelectTag.js +9 -11
  108. package/esm/core/Select/SelectTagContainer.js +2 -2
  109. package/esm/core/Stepper/Stepper.d.ts +4 -0
  110. package/esm/core/Stepper/Stepper.js +1 -0
  111. package/esm/core/Stepper/StepperStep.d.ts +4 -0
  112. package/esm/core/Stepper/StepperStep.js +2 -1
  113. package/esm/core/Table/Table.d.ts +1 -0
  114. package/esm/core/Table/Table.js +61 -47
  115. package/esm/core/Table/TablePaginator.js +16 -3
  116. package/esm/core/Table/actionHandlers/selectHandler.js +10 -7
  117. package/esm/core/Table/columns/selectionColumn.js +6 -1
  118. package/esm/core/Tree/Tree.js +1 -0
  119. package/esm/index.d.ts +1 -0
  120. package/esm/index.js +1 -0
  121. package/esm/styles.js +1 -1
  122. package/esm/utils/components/MiddleTextTruncation.d.ts +5 -7
  123. package/esm/utils/components/MiddleTextTruncation.js +22 -4
  124. package/esm/utils/components/OverflowContainer.d.ts +1 -0
  125. package/esm/utils/components/OverflowContainer.js +143 -4
  126. package/esm/utils/hooks/index.d.ts +1 -1
  127. package/esm/utils/hooks/index.js +1 -1
  128. package/esm/utils/hooks/useInstance.d.ts +22 -0
  129. package/esm/utils/hooks/useInstance.js +18 -0
  130. package/package.json +2 -2
  131. package/styles.css +8 -8
  132. package/DEV-cjs/utils/hooks/useOverflow.js +0 -76
  133. package/DEV-esm/utils/hooks/useOverflow.js +0 -63
  134. package/cjs/utils/hooks/useOverflow.d.ts +0 -23
  135. package/cjs/utils/hooks/useOverflow.js +0 -76
  136. package/esm/utils/hooks/useOverflow.d.ts +0 -23
  137. package/esm/utils/hooks/useOverflow.js +0 -63
@@ -29,8 +29,8 @@ export type DateRangePickerProps = {
29
29
  onChange?: (date: Date) => void;
30
30
  } | {
31
31
  enableRangeSelect: true;
32
- startDate: Date;
33
- endDate: Date;
32
+ startDate?: Date;
33
+ endDate?: Date;
34
34
  onChange?: (startDate: Date, endDate: Date) => void;
35
35
  };
36
36
  type DatePickerProps = {
@@ -148,6 +148,7 @@ const DatePicker = _react.forwardRef((props, forwardedRef) => {
148
148
  showDatesOutsideMonth = true,
149
149
  ...rest
150
150
  } = props;
151
+ let logWarning = (0, _index.useWarningLogger)();
151
152
  let monthNames = localizedNames?.months ?? defaultMonths;
152
153
  let shortDays = localizedNames?.shortDays ?? defaultShortDays;
153
154
  let longDays = localizedNames?.days ?? defaultLongDays;
@@ -192,7 +193,7 @@ const DatePicker = _react.forwardRef((props, forwardedRef) => {
192
193
  let popoverInitialFocusContext = _react.useContext(
193
194
  _Popover.PopoverInitialFocusContext,
194
195
  );
195
- _react.useLayoutEffect(() => {
196
+ (0, _index.useLayoutEffect)(() => {
196
197
  if (setFocus && popoverInitialFocusContext)
197
198
  popoverInitialFocusContext.setInitialFocus(-1);
198
199
  }, [popoverInitialFocusContext, setFocus]);
@@ -23,7 +23,7 @@ const _reacttransitiongroup = require('react-transition-group');
23
23
  const DialogComponent = _react.forwardRef((props, ref) => {
24
24
  let {
25
25
  trapFocus = false,
26
- setFocus = false,
26
+ setFocus = trapFocus,
27
27
  preventDocumentScroll = false,
28
28
  isOpen = false,
29
29
  isDismissible = true,
@@ -30,13 +30,17 @@ export type DialogContextProps = {
30
30
  */
31
31
  closeOnEsc?: boolean;
32
32
  /**
33
- * Traps the focus inside the dialog. This is useful when the dialog is modal.
33
+ * Prevents focus from leaving the dialog. This is useful when the dialog is modal.
34
+ *
35
+ * Setting this prop to `true` will also set `setFocus` to `true`.
36
+ *
34
37
  * @default false
35
38
  */
36
39
  trapFocus?: boolean;
37
40
  /**
38
41
  * If true, focuses the dialog.
39
- * @default false
42
+ *
43
+ * Defaults to `true` if `trapFocus` is set to `true`, otherwise defaults to `false`.
40
44
  */
41
45
  setFocus?: boolean;
42
46
  /**
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
3
3
  type NonIdealStateProps = {
4
4
  /**
5
- * An svg component, preferably from @itwin/itwinui-illustrations-react.
5
+ * An svg component, preferably from `@itwin/itwinui-illustrations-react`.
6
6
  *
7
7
  * @example
8
8
  * import { Svg404 } from '@itwin/itwinui-illustrations-react';
@@ -10,13 +10,17 @@ type NonIdealStateProps = {
10
10
  */
11
11
  svg: React.ReactNode;
12
12
  /**
13
- * Primary heading for the error page
13
+ * Primary heading for the `NonIdealState`
14
14
  */
15
15
  heading?: React.ReactNode;
16
16
  /**
17
17
  * Secondary text to explain the error
18
18
  * Can include html in order to provide a hyperlink
19
- * E.g. `Please visit <a href="https://www.bentley.com/help">our support page</a> for help.`
19
+ *
20
+ * @example
21
+ * <>
22
+ * Please visit <Anchor href="https://www.bentley.com/help">our support page</Anchor> for help.
23
+ * </>
20
24
  */
21
25
  description?: React.ReactNode;
22
26
  /**
@@ -24,13 +28,13 @@ type NonIdealStateProps = {
24
28
  * Typically should be a primary and secondary button.
25
29
  *
26
30
  * @example
27
- * <ErrorPage
28
- * actions={
29
- * <>
30
- * <Button styleType={'high-visibility'}>Retry</Button>
31
- * <Button>Contact us</Button>
32
- * </>
33
- * }
31
+ * <NonIdealState
32
+ * actions={
33
+ * <>
34
+ * <Button styleType={'high-visibility'}>Retry</Button>
35
+ * <Button>Contact us</Button>
36
+ * </>
37
+ * }
34
38
  * />
35
39
  */
36
40
  actions?: React.ReactNode;
@@ -53,7 +57,7 @@ type NonIdealStateProps = {
53
57
  };
54
58
  /**
55
59
  * A stylized display to communicate common http errors and other non-ideal states.
56
- * Works well with svgs from @itwin/itwinui-illustrations-react.
60
+ * Works well with svgs from `@itwin/itwinui-illustrations-react`.
57
61
  *
58
62
  * @example
59
63
  * <NonIdealState svg={<Svg404 />} heading='Not found' />
@@ -0,0 +1,174 @@
1
+ import * as React from 'react';
2
+ import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
3
+ import { Text } from '../Typography/Text.js';
4
+ import type { FocusEntry, PanelsInstance, TriggerMapEntry } from './helpers.js';
5
+ type PanelsWrapperProps = {
6
+ /**
7
+ * Function that gets called when the active panel is changed.
8
+ */
9
+ onActiveIdChange?: (newActiveId: string) => void;
10
+ children: React.ReactNode;
11
+ /**
12
+ * Pass an instance created by `useInstance` to control the panels imperatively.
13
+ *
14
+ * @example
15
+ * const panels = Panels.useInstance();
16
+ * <Panels instance={panels} />
17
+ */
18
+ instance?: PanelsInstance;
19
+ };
20
+ export declare const PanelsWrapper: PolymorphicForwardRefComponent<"div", PanelsWrapperProps>;
21
+ export declare const PanelsWrapperContext: React.Context<{
22
+ activePanelId: string | undefined;
23
+ setActivePanelId: React.Dispatch<React.SetStateAction<string>>;
24
+ /**
25
+ * Simpler alternative to a full history stack.
26
+ *
27
+ * ```
28
+ * Record<
29
+ * string, // Id of a panel
30
+ * {
31
+ * triggerId: string, // Id of the trigger element that points to this panel
32
+ * panelId: string, // Id of the panel element in which the trigger is present
33
+ * }
34
+ * >
35
+ * ```
36
+ */
37
+ triggers: Record<string, TriggerMapEntry>;
38
+ setTriggers: React.Dispatch<React.SetStateAction<Record<string, TriggerMapEntry>>>;
39
+ changeActivePanel: (newActiveId: string) => void;
40
+ shouldFocus: FocusEntry;
41
+ setShouldFocus: React.Dispatch<React.SetStateAction<FocusEntry>>;
42
+ panels: React.MutableRefObject<Set<string>>;
43
+ } | undefined>;
44
+ type PanelProps = {
45
+ id: string;
46
+ };
47
+ type PanelTriggerProps = {
48
+ for: string;
49
+ children: React.ReactElement;
50
+ };
51
+ type PanelHeaderProps = {
52
+ titleProps?: React.ComponentProps<typeof Text>;
53
+ };
54
+ export declare const Panels: {
55
+ /**
56
+ * Component that manages the logic for layered panels.
57
+ * It can be used anywhere to create layers. E.g. `Menu`, `InformationPanel`, `Popover`, etc.
58
+ *
59
+ * Requirements:
60
+ * - The initial displayed Panel should be the first `Panel` in the `Panels.Wrapper`.
61
+ * - A panel can have only one trigger pointing to it. i.e. out of all the triggers across all panels,
62
+ * only one can point to a particular panel.
63
+ * - The `Panels.Panel`s within the wrapper should be in the order of the navigation. E.g.:
64
+ * ```jsx
65
+ * <Panels.Wrapper>
66
+ * <Panels.Panel id={root} /> // Must come before moreDetails since it contains the trigger to moreDetails
67
+ * <Panels.Panel id={moreDetails}> // Must come after root since it is navigated to from root
68
+ * </Panels.Wrapper>
69
+ * ```
70
+ *
71
+ * @example
72
+ * <Panels.Wrapper as={Surface}>
73
+ * <Panels.Panel
74
+ * id={panelIdRoot}
75
+ * as={Surface}
76
+ * border={false}
77
+ * elevation={0}
78
+ * >
79
+ * <Surface.Header as={Panels.Header}>Root</Surface.Header>
80
+ * <Surface.Body as={List}>
81
+ * <ListItem>
82
+ * <Panels.Trigger for={panelIdMoreInfo}>
83
+ * <ListItem.Action>More details</ListItem.Action>
84
+ * </Panels.Trigger>
85
+ * </ListItem>
86
+ * </Surface.Body>
87
+ * </Panels.Panel>
88
+ *
89
+ * <Panels.Panel
90
+ * id={panelIdMoreInfo}
91
+ * as={Surface}
92
+ * border={false}
93
+ * elevation={0}
94
+ * >
95
+ * <Surface.Header as={Panels.Header}>More details</Surface.Header>
96
+ * <Surface.Body isPadded>
97
+ * <Text>Content</Text>
98
+ * </Surface.Body>
99
+ * </Panels.Panel>
100
+ * </Panels.Wrapper>
101
+ */
102
+ Wrapper: PolymorphicForwardRefComponent<"div", PanelsWrapperProps>;
103
+ /**
104
+ * Takes an `id` and the panel content.
105
+ * Match this `id` with a `Panels.Triggers`'s `for` prop to create a link between them.
106
+ *
107
+ * @example
108
+ * <Panels.Panel id={panelIdRoot} as={Surface} border={false} elevation={0}>
109
+ * <Surface.Header as={Panels.Header}>Root</Surface.Header>
110
+ * <Surface.Body as={List}>
111
+ * <ListItem>
112
+ * <Panels.Trigger for={panelIdMoreInfo}>
113
+ * <ListItem.Action>More details</ListItem.Action>
114
+ * </Panels.Trigger>
115
+ * </ListItem>
116
+ * </Surface.Body>
117
+ * </Panels.Panel>
118
+ */
119
+ Panel: PolymorphicForwardRefComponent<"div", PanelProps>;
120
+ /**
121
+ * Wraps the clickable element and appends an `onClick` to change the active panel to the one specified in the `for`
122
+ * prop. Also appends some attributes for accessibility.
123
+ *
124
+ * @example
125
+ * <Panels.Trigger for={nextPanelId}>
126
+ * <Button>go to next panel</Button>
127
+ * </Panels.Trigger>
128
+ *
129
+ * @example
130
+ * <ListItem>
131
+ * <Panels.Trigger for={panelIdMoreInfo}>
132
+ * <ListItem.Action>More details</ListItem.Action>
133
+ * </Panels.Trigger>
134
+ * </ListItem>
135
+ */
136
+ Trigger: {
137
+ (props: PanelTriggerProps): string | number | true | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null;
138
+ displayName: string;
139
+ };
140
+ /**
141
+ * Required component to add an accessible name and also a back button (if previous panel exists) to the panel.
142
+ *
143
+ * @example
144
+ * <Panels.Panel id={panelIdRoot}>
145
+ * <Panels.Header>Root</Panels.Header>
146
+ * …
147
+ * </Panels.Panel>
148
+ *
149
+ * @example
150
+ * <Panels.Panel
151
+ * id={panelIdMoreInfo}
152
+ * as={Surface}
153
+ * border={false}
154
+ * elevation={0}
155
+ * >
156
+ * <Surface.Header as={Panels.Header}>More details</Surface.Header>
157
+ * <Surface.Body isPadded>
158
+ * <Text>Content</Text>
159
+ * </Surface.Body>
160
+ * </Panels.Panel>
161
+ */
162
+ Header: PolymorphicForwardRefComponent<"div", PanelHeaderProps>;
163
+ /**
164
+ * You can use methods from `Panels.useInstance()` to control the state programmatically.
165
+ *
166
+ * @example
167
+ * const panels = Panels.useInstance();
168
+ *
169
+ * <Button onClick={() => panels.goBack()}>Go back</Button>
170
+ * <Panels.Wrapper instance={panels}>{…}</Panels.Wrapper>;
171
+ */
172
+ useInstance: () => PanelsInstance;
173
+ };
174
+ export {};
@@ -0,0 +1,312 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, '__esModule', {
3
+ value: true,
4
+ });
5
+ function _export(target, all) {
6
+ for (var name in all)
7
+ Object.defineProperty(target, name, {
8
+ enumerable: true,
9
+ get: all[name],
10
+ });
11
+ }
12
+ _export(exports, {
13
+ Panels: function () {
14
+ return Panels;
15
+ },
16
+ PanelsWrapper: function () {
17
+ return PanelsWrapper;
18
+ },
19
+ PanelsWrapperContext: function () {
20
+ return PanelsWrapperContext;
21
+ },
22
+ });
23
+ const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
24
+ const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
25
+ const _react = _interop_require_wildcard._(require('react'));
26
+ const _reactdom = _interop_require_wildcard._(require('react-dom'));
27
+ const _index = require('../../utils/index.js');
28
+ const _IconButton = require('../Buttons/IconButton.js');
29
+ const _Flex = require('../Flex/Flex.js');
30
+ const _Text = require('../Typography/Text.js');
31
+ const _classnames = _interop_require_default._(require('classnames'));
32
+ const _helpers = require('./helpers.js');
33
+ const PanelsWrapper = _react.forwardRef((props, forwardedRef) => {
34
+ let {
35
+ children,
36
+ className,
37
+ onActiveIdChange: onActiveIdChangeProp,
38
+ instance,
39
+ ...rest
40
+ } = props;
41
+ let onActiveIdChange = (0, _index.useLatestRef)(onActiveIdChangeProp);
42
+ let ref = _react.useRef(null);
43
+ let [activePanelId, setActivePanelId] = _react.useState(void 0);
44
+ let [triggers, setTriggers] = _react.useState({});
45
+ let panels = _react.useRef(new Set());
46
+ let [shouldFocus, setShouldFocus] = _react.useState(void 0);
47
+ let motionOk = (0, _index.useMediaQuery)(
48
+ '(prefers-reduced-motion: no-preference)',
49
+ );
50
+ let changeActivePanel = _react.useCallback(
51
+ (newActiveId) => {
52
+ if (!panels.current.has(newActiveId) || newActiveId === activePanelId)
53
+ return;
54
+ _reactdom.flushSync(() => setActivePanelId(newActiveId));
55
+ onActiveIdChange.current?.(newActiveId);
56
+ ref.current?.ownerDocument.getElementById(newActiveId)?.scrollIntoView({
57
+ block: 'nearest',
58
+ inline: 'center',
59
+ behavior: motionOk ? 'smooth' : 'instant',
60
+ });
61
+ },
62
+ [activePanelId, motionOk, onActiveIdChange],
63
+ );
64
+ return _react.createElement(
65
+ PanelsWrapperContext.Provider,
66
+ {
67
+ value: _react.useMemo(
68
+ () => ({
69
+ activePanelId,
70
+ setActivePanelId,
71
+ changeActivePanel,
72
+ triggers,
73
+ setTriggers,
74
+ shouldFocus,
75
+ setShouldFocus,
76
+ panels,
77
+ }),
78
+ [
79
+ activePanelId,
80
+ changeActivePanel,
81
+ setActivePanelId,
82
+ setTriggers,
83
+ shouldFocus,
84
+ triggers,
85
+ ],
86
+ ),
87
+ },
88
+ _react.createElement(
89
+ _helpers.PanelsInstanceProvider,
90
+ {
91
+ instance: instance,
92
+ },
93
+ _react.createElement(
94
+ _index.Box,
95
+ {
96
+ ref: (0, _index.useMergedRefs)(ref, forwardedRef),
97
+ ...rest,
98
+ className: (0, _classnames.default)('iui-panel-wrapper', className),
99
+ },
100
+ children,
101
+ ),
102
+ ),
103
+ );
104
+ });
105
+ const PanelsWrapperContext = _react.createContext(void 0);
106
+ const Panel = _react.forwardRef((props, forwardedRef) => {
107
+ let { id, children, className, ...rest } = props;
108
+ let { activePanelId, triggers, panels, setActivePanelId } = (0,
109
+ _index.useSafeContext)(PanelsWrapperContext);
110
+ let associatedTrigger = _react.useMemo(() => triggers[id], [id, triggers]);
111
+ let previousActivePanelId = useDelayed(activePanelId) || activePanelId;
112
+ let isMounted = [activePanelId, previousActivePanelId].includes(id);
113
+ let isTransitioning =
114
+ activePanelId === id && activePanelId !== previousActivePanelId;
115
+ let isInert = previousActivePanelId === id && activePanelId !== id;
116
+ (0, _index.useLayoutEffect)(() => {
117
+ let isFirstPanel = null == activePanelId && 0 === panels.current.size;
118
+ if (isFirstPanel) setActivePanelId(id);
119
+ let panelsCurrent = panels.current;
120
+ if (!panelsCurrent.has(id)) panelsCurrent.add(id);
121
+ return () => {
122
+ panelsCurrent.delete(id);
123
+ };
124
+ }, [activePanelId, id, panels, setActivePanelId]);
125
+ return _react.createElement(
126
+ PanelContext.Provider,
127
+ {
128
+ value: _react.useMemo(
129
+ () => ({
130
+ id,
131
+ associatedTrigger,
132
+ }),
133
+ [associatedTrigger, id],
134
+ ),
135
+ },
136
+ isMounted &&
137
+ _react.createElement(
138
+ _index.Box,
139
+ {
140
+ ref: forwardedRef,
141
+ id: id,
142
+ className: (0, _classnames.default)('iui-panel', className),
143
+ 'aria-labelledby': `${id}-header-title`,
144
+ role: 'group',
145
+ inert: isInert ? '' : void 0,
146
+ 'data-iui-transitioning': isTransitioning ? 'true' : void 0,
147
+ ...rest,
148
+ },
149
+ children,
150
+ ),
151
+ );
152
+ });
153
+ const PanelContext = _react.createContext(void 0);
154
+ const PanelTrigger = (props) => {
155
+ let { children, for: forProp } = props;
156
+ let {
157
+ changeActivePanel,
158
+ triggers,
159
+ setTriggers,
160
+ activePanelId: activePanel,
161
+ shouldFocus,
162
+ setShouldFocus,
163
+ panels,
164
+ } = (0, _index.useSafeContext)(PanelsWrapperContext);
165
+ let { id: panelId } = (0, _index.useSafeContext)(PanelContext);
166
+ let fallbackId = _react.useId();
167
+ let triggerId = children.props.id || fallbackId;
168
+ let onClick = _react.useCallback(() => {
169
+ if (null == activePanel) return;
170
+ setShouldFocus({
171
+ fromPanelId: activePanel,
172
+ toPanelId: forProp,
173
+ direction: 'forward',
174
+ });
175
+ changeActivePanel?.(forProp);
176
+ }, [activePanel, changeActivePanel, forProp, setShouldFocus]);
177
+ let focusRef = _react.useCallback(
178
+ (el) => {
179
+ if (
180
+ shouldFocus?.direction === 'backward' &&
181
+ shouldFocus?.toPanelId === panelId &&
182
+ shouldFocus?.fromPanelId === forProp
183
+ ) {
184
+ el?.focus({
185
+ preventScroll: true,
186
+ });
187
+ setShouldFocus(void 0);
188
+ }
189
+ },
190
+ [forProp, panelId, setShouldFocus, shouldFocus],
191
+ );
192
+ let logWarning = (0, _index.useWarningLogger)();
193
+ _react.useEffect(() => {
194
+ if (!panels.current.has(forProp))
195
+ logWarning(
196
+ `Panels.Trigger's \`for\` prop ("${forProp}") corresponds to no Panel.`,
197
+ );
198
+ }, [forProp, logWarning, panels, triggers]);
199
+ _react.useEffect(() => {
200
+ setTriggers((oldTriggers) => {
201
+ let triggersMatch = oldTriggers[forProp];
202
+ if (
203
+ null == triggersMatch ||
204
+ panelId !== triggersMatch.panelId ||
205
+ triggerId !== triggersMatch.triggerId
206
+ )
207
+ return {
208
+ ...oldTriggers,
209
+ [forProp]: {
210
+ panelId,
211
+ triggerId,
212
+ },
213
+ };
214
+ return oldTriggers;
215
+ });
216
+ }, [forProp, panelId, setTriggers, triggerId]);
217
+ return (0, _index.cloneElementWithRef)(children, (children) => ({
218
+ ...children.props,
219
+ id: triggerId,
220
+ ref: focusRef,
221
+ onClick: (0, _index.mergeEventHandlers)(children.props.onClick, onClick),
222
+ 'aria-expanded': activePanel === forProp,
223
+ 'aria-controls': forProp,
224
+ }));
225
+ };
226
+ const PanelHeader = _react.forwardRef((props, forwardedRef) => {
227
+ let { titleProps, children, ...rest } = props;
228
+ let { shouldFocus, setShouldFocus } = (0, _index.useSafeContext)(
229
+ PanelsWrapperContext,
230
+ );
231
+ let { id: panelId, associatedTrigger: panelAssociatedTrigger } = (0,
232
+ _index.useSafeContext)(PanelContext);
233
+ let focusRef = _react.useCallback(
234
+ (el) => {
235
+ if (
236
+ shouldFocus?.direction === 'forward' &&
237
+ shouldFocus.toPanelId === panelId
238
+ ) {
239
+ el?.focus({
240
+ preventScroll: true,
241
+ });
242
+ setShouldFocus(void 0);
243
+ }
244
+ },
245
+ [panelId, setShouldFocus, shouldFocus?.direction, shouldFocus?.toPanelId],
246
+ );
247
+ return _react.createElement(
248
+ _Flex.Flex,
249
+ {
250
+ ref: forwardedRef,
251
+ ...rest,
252
+ },
253
+ panelAssociatedTrigger && _react.createElement(PanelBackButton, null),
254
+ _react.createElement(
255
+ _Text.Text,
256
+ {
257
+ id: `${panelId}-header-title`,
258
+ as: 'h2',
259
+ tabIndex: -1,
260
+ ref: focusRef,
261
+ ...titleProps,
262
+ },
263
+ children,
264
+ ),
265
+ );
266
+ });
267
+ const PanelBackButton = _react.forwardRef((props, forwardedRef) => {
268
+ let { children, onClick, ...rest } = props;
269
+ let { instance: panelInstance } = (0, _index.useSafeContext)(
270
+ _helpers.PanelsInstanceContext,
271
+ );
272
+ return _react.createElement(
273
+ _IconButton.IconButton,
274
+ {
275
+ ref: forwardedRef,
276
+ 'aria-label': 'Previous panel',
277
+ styleType: 'borderless',
278
+ size: 'small',
279
+ 'data-iui-shift': 'left',
280
+ ...rest,
281
+ onClick: (0, _index.mergeEventHandlers)(
282
+ _react.useCallback(() => panelInstance?.goBack(), [panelInstance]),
283
+ onClick,
284
+ ),
285
+ },
286
+ children || _react.createElement(_index.SvgChevronLeft, null),
287
+ );
288
+ });
289
+ const Panels = {
290
+ Wrapper: PanelsWrapper,
291
+ Panel,
292
+ Trigger: PanelTrigger,
293
+ Header: PanelHeader,
294
+ useInstance: _index.useInstance,
295
+ };
296
+ function useDelayed(
297
+ value,
298
+ { delay } = {
299
+ delay: 500,
300
+ },
301
+ ) {
302
+ let [delayed, setDelayed] = _react.useState(void 0);
303
+ let timeout = _react.useRef(void 0);
304
+ _react.useEffect(() => {
305
+ if (0 === delay) setDelayed(value);
306
+ else timeout.current = setTimeout(() => setDelayed(value), delay);
307
+ return () => {
308
+ clearTimeout(timeout.current);
309
+ };
310
+ }, [value, delay]);
311
+ return delayed;
312
+ }
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ export type PanelsInstance = {
3
+ /** Go back to the panel that has a trigger that points to the current panel. */
4
+ goBack: () => void;
5
+ };
6
+ export type TriggerMapEntry = {
7
+ triggerId: string;
8
+ panelId: string;
9
+ };
10
+ export type FocusEntry = {
11
+ fromPanelId: string;
12
+ toPanelId: string;
13
+ direction: 'forward' | 'backward';
14
+ } | undefined;
15
+ export declare const PanelsInstanceContext: React.Context<{
16
+ instance: PanelsInstance;
17
+ } | undefined>;
18
+ type PanelInstanceProviderProps = {
19
+ children: React.ReactNode;
20
+ instance: PanelsInstance | undefined;
21
+ };
22
+ export declare const PanelsInstanceProvider: (props: PanelInstanceProviderProps) => React.JSX.Element;
23
+ export {};
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, '__esModule', {
3
+ value: true,
4
+ });
5
+ function _export(target, all) {
6
+ for (var name in all)
7
+ Object.defineProperty(target, name, {
8
+ enumerable: true,
9
+ get: all[name],
10
+ });
11
+ }
12
+ _export(exports, {
13
+ PanelsInstanceContext: function () {
14
+ return PanelsInstanceContext;
15
+ },
16
+ PanelsInstanceProvider: function () {
17
+ return PanelsInstanceProvider;
18
+ },
19
+ });
20
+ const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
21
+ const _react = _interop_require_wildcard._(require('react'));
22
+ const _index = require('../../utils/index.js');
23
+ const _Panels = require('./Panels.js');
24
+ const PanelsInstanceContext = _react.createContext(void 0);
25
+ const PanelsInstanceProvider = (props) => {
26
+ let { children, instance: instanceProp } = props;
27
+ let instanceBackup = _Panels.Panels.useInstance();
28
+ let instance = instanceProp || instanceBackup;
29
+ let { activePanelId, changeActivePanel, triggers, setShouldFocus } = (0,
30
+ _index.useSafeContext)(_Panels.PanelsWrapperContext);
31
+ let goBack = _react.useCallback(async () => {
32
+ if (null == activePanelId) return;
33
+ let trigger = triggers[activePanelId];
34
+ if (null != trigger.triggerId) {
35
+ setShouldFocus({
36
+ fromPanelId: activePanelId,
37
+ toPanelId: trigger.panelId,
38
+ direction: 'backward',
39
+ });
40
+ changeActivePanel(trigger.panelId);
41
+ }
42
+ }, [activePanelId, changeActivePanel, setShouldFocus, triggers]);
43
+ (0, _index.useSynchronizeInstance)(
44
+ instance,
45
+ _react.useMemo(
46
+ () => ({
47
+ goBack,
48
+ }),
49
+ [goBack],
50
+ ),
51
+ );
52
+ return _react.createElement(
53
+ PanelsInstanceContext.Provider,
54
+ {
55
+ value: {
56
+ instance,
57
+ },
58
+ },
59
+ children,
60
+ );
61
+ };