@splunk/react-ui 5.7.0 → 5.8.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 (138) hide show
  1. package/Accordion.js +6 -6
  2. package/Box.js +83 -34
  3. package/CHANGELOG.md +34 -0
  4. package/CollapsiblePanel.js +11 -11
  5. package/ComboBox.js +31 -27
  6. package/ControlGroup.js +92 -91
  7. package/DefinitionList.js +9 -9
  8. package/Drawer.d.ts +2 -0
  9. package/Drawer.js +679 -0
  10. package/DualListbox.js +1 -1
  11. package/JSONTree.js +73 -72
  12. package/Link.js +2 -2
  13. package/MIGRATION.md +10 -0
  14. package/Menu.js +338 -240
  15. package/Modal.js +127 -109
  16. package/Multiselect.js +437 -351
  17. package/Paginator.js +14 -12
  18. package/Popover.js +4 -1
  19. package/README.md +11 -0
  20. package/RadioBar.js +1 -1
  21. package/Search.js +103 -88
  22. package/Select.js +42 -40
  23. package/SelectBase.js +374 -328
  24. package/SidePanel.js +346 -167
  25. package/SlidingPanels.js +11 -11
  26. package/StepBar.js +7 -7
  27. package/Switch.js +5 -5
  28. package/Text.js +24 -24
  29. package/TextArea.js +7 -7
  30. package/TransitionOpen.js +204 -185
  31. package/docs-llm/Accordion.md +267 -0
  32. package/docs-llm/Anchor Menu.md +115 -0
  33. package/docs-llm/Anchor.md +54 -0
  34. package/docs-llm/AnimationToggle.md +254 -0
  35. package/docs-llm/Avatar.md +298 -0
  36. package/docs-llm/Badge.md +212 -0
  37. package/docs-llm/Breadcrumbs.md +306 -0
  38. package/docs-llm/Button Group.md +53 -0
  39. package/docs-llm/Button.md +361 -0
  40. package/docs-llm/Card Layout.md +286 -0
  41. package/docs-llm/Card.md +619 -0
  42. package/docs-llm/Checkbox.md +218 -0
  43. package/docs-llm/Chip.md +291 -0
  44. package/docs-llm/Clickable.md +160 -0
  45. package/docs-llm/Code.md +292 -0
  46. package/docs-llm/Collapsible Panel.md +744 -0
  47. package/docs-llm/Color.md +253 -0
  48. package/docs-llm/Column Layout.md +391 -0
  49. package/docs-llm/Combo Box.md +540 -0
  50. package/docs-llm/Control Group.md +594 -0
  51. package/docs-llm/Date.md +270 -0
  52. package/docs-llm/Definition List.md +278 -0
  53. package/docs-llm/Divider.md +216 -0
  54. package/docs-llm/Drawer.md +414 -0
  55. package/docs-llm/Dropdown.md +472 -0
  56. package/docs-llm/Dual Listbox.md +325 -0
  57. package/docs-llm/File.md +653 -0
  58. package/docs-llm/Form Rows.md +374 -0
  59. package/docs-llm/Heading.md +179 -0
  60. package/docs-llm/Image.md +109 -0
  61. package/docs-llm/JSON Tree.md +260 -0
  62. package/docs-llm/Layer.md +74 -0
  63. package/docs-llm/Layout.md +50 -0
  64. package/docs-llm/Link.md +318 -0
  65. package/docs-llm/List.md +189 -0
  66. package/docs-llm/Markdown.md +179 -0
  67. package/docs-llm/Menu.md +735 -0
  68. package/docs-llm/Message Bar.md +236 -0
  69. package/docs-llm/Message.md +248 -0
  70. package/docs-llm/Modal.md +443 -0
  71. package/docs-llm/Monogram.md +159 -0
  72. package/docs-llm/Multiselect.md +937 -0
  73. package/docs-llm/Number.md +298 -0
  74. package/docs-llm/Paginator.md +395 -0
  75. package/docs-llm/Paragraph.md +148 -0
  76. package/docs-llm/Phone Number.md +254 -0
  77. package/docs-llm/Popover.md +166 -0
  78. package/docs-llm/Progress.md +141 -0
  79. package/docs-llm/Radio Bar.md +303 -0
  80. package/docs-llm/Radio List.md +350 -0
  81. package/docs-llm/Resize.md +362 -0
  82. package/docs-llm/Screen Reader Content.md +73 -0
  83. package/docs-llm/Scroll Container Context.md +155 -0
  84. package/docs-llm/Scroll.md +152 -0
  85. package/docs-llm/Search.md +381 -0
  86. package/docs-llm/Select.md +985 -0
  87. package/docs-llm/Side Panel.md +777 -0
  88. package/docs-llm/Slider.md +339 -0
  89. package/docs-llm/Sliding Panels.md +340 -0
  90. package/docs-llm/Split Button.md +295 -0
  91. package/docs-llm/Static Content.md +90 -0
  92. package/docs-llm/Step Bar.md +292 -0
  93. package/docs-llm/Switch.md +268 -0
  94. package/docs-llm/Tab Bar.md +439 -0
  95. package/docs-llm/Tab Layout.md +398 -0
  96. package/docs-llm/Table.md +2642 -0
  97. package/docs-llm/Text Area.md +253 -0
  98. package/docs-llm/Text.md +339 -0
  99. package/docs-llm/Tooltip.md +325 -0
  100. package/docs-llm/Transition Open.md +406 -0
  101. package/docs-llm/Tree.md +586 -0
  102. package/docs-llm/Typography.md +125 -0
  103. package/docs-llm/Wait Spinner.md +121 -0
  104. package/docs-llm/llms.txt +97 -0
  105. package/package.json +6 -5
  106. package/types/src/Box/Box.d.ts +2 -10
  107. package/types/src/Drawer/Body.d.ts +17 -0
  108. package/types/src/Drawer/Drawer.d.ts +114 -0
  109. package/types/src/Drawer/DrawerContext.d.ts +11 -0
  110. package/types/src/Drawer/Footer.d.ts +25 -0
  111. package/types/src/Drawer/Header.d.ts +41 -0
  112. package/types/src/Drawer/docs/examples/Basic.d.ts +6 -0
  113. package/types/src/Drawer/docs/examples/ContainerPosition.d.ts +7 -0
  114. package/types/src/Drawer/docs/examples/InitialFocus.d.ts +9 -0
  115. package/types/src/Drawer/docs/examples/InlinePosition.d.ts +7 -0
  116. package/types/src/Drawer/docs/examples/PagePosition.d.ts +7 -0
  117. package/types/src/Drawer/index.d.ts +2 -0
  118. package/types/src/JSONTree/JSONTree.d.ts +12 -5
  119. package/types/src/JSONTree/renderTreeItems.d.ts +2 -1
  120. package/types/src/Menu/Item.d.ts +2 -1
  121. package/types/src/Menu/docs/examples/SelectableCheckbox.d.ts +7 -0
  122. package/types/src/Modal/Modal.d.ts +1 -2
  123. package/types/src/Select/Option.d.ts +6 -3
  124. package/types/src/Select/Select.d.ts +8 -5
  125. package/types/src/Select/docs/examples/Dimmed.d.ts +7 -0
  126. package/types/src/SelectBase/OptionBase.d.ts +6 -3
  127. package/types/src/SelectBase/SelectBase.d.ts +8 -3
  128. package/types/src/SidePanel/SidePanel.d.ts +43 -2
  129. package/types/src/SidePanel/docs/examples/DockLayout.d.ts +17 -0
  130. package/types/src/SidePanel/docs/examples/InitialFocus.d.ts +9 -0
  131. package/types/src/TransitionOpen/TransitionOpen.d.ts +29 -4
  132. package/types/src/useKeyPress/index.d.ts +9 -2
  133. package/types/src/useOnClickOutside/index.d.ts +2 -0
  134. package/types/src/useOnClickOutside/useOnClickOutside.d.ts +4 -0
  135. package/useKeyPress.js +23 -18
  136. package/useOnClickOutside.d.ts +2 -0
  137. package/useOnClickOutside.js +79 -0
  138. package/types/src/RadioList/docs/examples/Row.d.ts +0 -6
@@ -0,0 +1,141 @@
1
+ # Progress
2
+
3
+ ## Overview
4
+
5
+
6
+ > Image: Illustration of a Progress component.
7
+
8
+
9
+ ## When to use this component
10
+ - When users need feedback on the status of an ongoing task.
11
+ - To show the length of a process and track its progression toward completion.
12
+ - When the process is complex and has a long wait time.
13
+ - When the percentage of the completed process can be determined.
14
+ - To convey that data is being requested, transferred, or processed.
15
+
16
+ ## When to use another component
17
+ - For short wait times, use a Wait Spinner.
18
+ - For related tasks that need to be completed in a linear sequence, use a Step Bar.
19
+
20
+ ```mermaid
21
+ graph TD
22
+ accDescr: Decision tree that guides on when to use the Progress component or something else
23
+ A(Is the task expected to take less than a few seconds?) -- Yes --- B(Wait Spinner)
24
+ A -- No --- C(Are the tasks sequential and related?)
25
+ C -- Yes --- D(Step Bar)
26
+ C -- No --- E(Progress)
27
+ ```
28
+
29
+ ### Check out
30
+ - [Wait Spinner][1]
31
+ - [Step Bar][2]
32
+
33
+ ## Usage
34
+
35
+ ### Grouping
36
+ Display overall progress of a group rather than the progress of each item in the group.
37
+
38
+ > Image: Example showing grouping of content while using the progress component. The first example with the heart eyes emoji displays the progress component at the top of the page, loading for all the contents on the page, whereas the second example with the grimacing emoji displays the progress component loading for all content sections individually.
39
+
40
+
41
+ ### Labels
42
+ Labels should always be placed below the progress bar contained in a tooltip for accessibility. Avoid placing text inside the progress bar, this could cause clutter and poor text readability.
43
+
44
+ > Image: Example showing how labels should appear while using the progress component. The first example with the heart eyes emoji displays the context label (percentage complete) inside a tool tip under the progress component, whereas the second example with the grimacing emoji displays the context label inside the progress component.
45
+
46
+
47
+ ### Screen real estate
48
+ Avoid using the progress component in small spaces such as within a button.
49
+
50
+ > Image: Example showing appropriate screen realestate for the progress component. The first example with the heart eyes emoji displays the progress component at the top of the screen, taking up a good amount of screen real estate, whereas the second example with the grimacing emoji displays the progress component cramped inside a button component.
51
+
52
+
53
+ ### Quantifiable processes
54
+ Use a progress bar for processes that can be quantified, such as displaying a percentage (e.g., file upload). Avoid using it for stepped progress determined by user actions.
55
+
56
+ > Image: Example showing what processes the label component should be used for. The first example with the heart eyes emoji displays the progress component used to showcase upload time within a table, whereas the second example with the grimacing emoji displays the progress component used to determine a user
57
+
58
+
59
+ [1]: ./WaitSpinner
60
+ [2]: ./StepBar
61
+
62
+ ## Examples
63
+
64
+
65
+ ### Basic
66
+
67
+ ```typescript
68
+ import React, { useState, useEffect } from 'react';
69
+
70
+ import Progress from '@splunk/react-ui/Progress';
71
+
72
+
73
+ function Example() {
74
+ const [percentage, setPercentage] = useState(0);
75
+
76
+ useEffect(() => {
77
+ const timer = window.setInterval(() => {
78
+ setPercentage((currentPercentage) => {
79
+ if (currentPercentage >= 100) {
80
+ return 0;
81
+ }
82
+ return currentPercentage + 5;
83
+ });
84
+ }, 1000);
85
+ return () => {
86
+ window.clearInterval(timer);
87
+ };
88
+ }, []);
89
+
90
+ return <Progress percentage={percentage} tooltip={`${percentage}% uploaded`} />;
91
+ }
92
+
93
+ export default Example;
94
+ ```
95
+
96
+
97
+
98
+ ### Type
99
+
100
+ ```typescript
101
+ import React from 'react';
102
+
103
+ import Progress from '@splunk/react-ui/Progress';
104
+
105
+
106
+ function Type() {
107
+ return (
108
+ <>
109
+ <Progress type="info" percentage={30} />
110
+ <br />
111
+ <Progress type="success" percentage={60} />
112
+ <br />
113
+ <Progress type="error" percentage={100} />
114
+ </>
115
+ );
116
+ }
117
+
118
+ export default Type;
119
+ ```
120
+
121
+
122
+
123
+
124
+ ## API
125
+
126
+
127
+ ### Progress API
128
+
129
+ #### Props
130
+
131
+ | Name | Type | Required | Default | Description |
132
+ |------|------|------|------|------|
133
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts and null when it unmounts. |
134
+ | percentage | number | no | | The percentage complete. If unset, no progress bar is shown. Percentage must be a number from 0-100. |
135
+ | tooltip | React.ReactNode | no | | Tooltip defaults to the percentage complete. |
136
+ | type | 'info' \| 'success' \| 'error' | no | 'info' | Sets the appearance of the `Progress` component. Note: `success` and `error` types are not animated. |
137
+
138
+
139
+
140
+
141
+
@@ -0,0 +1,303 @@
1
+ # Radio Bar
2
+
3
+ ## Overview
4
+
5
+
6
+ > Image: Illustration of a Radio Bar component.
7
+
8
+
9
+ ## When to use this component
10
+ - For quick selection within a form. Use only if there are less than 8 options that are simple and straightforward.
11
+ - As a filter for related content (e.g. filter messages by “All”, “Read”, and “Unread”).
12
+ - Useful to switch between alternate views of the same set of data in the same context. (e.g. list view, grid view, or map view).
13
+ - If additional visual affordances and adornments, such as icons, can provide separation between options.
14
+
15
+ ## When to use another component
16
+ - If vertical space is not a concern or the options labels are long, use Radio List.
17
+ - For binary selections like “on/off”, “yes/no”, “true/false”, consider using a Switch - Toggle.
18
+ - Use Tab Bar to change the entire display of different sets of data, as a form of navigation.
19
+
20
+ ```mermaid
21
+ graph TD
22
+ accDescr: Decision tree that guides on when to use the RadioBar component or something else
23
+ A(Are users selecting an option in the context of a form?) -- Yes --- B(Are there fewer than 8 options?)
24
+ B -- Yes --- C(Do the options have long labels or you don't need to conserve vertical space?)
25
+ C -- Yes --- D(Radio List)
26
+ C -- No --- E(Radio Bar)
27
+ B -- No --- F(Select or Combo Box)
28
+ A -- No --- G(Do the options work as a form of navigation or switch between completely different content?)
29
+ G -- Yes --- H(Tabs)
30
+ G -- No --- I(Radio Bar)
31
+ ```
32
+
33
+ ### Check out
34
+ - [Radio List][1]
35
+ - [Switch][2]
36
+ - [Tab Bar][3]
37
+ - [Select][4]
38
+ - [Combo Box][5]
39
+
40
+ ## Usage
41
+
42
+ ### Inutitive icons
43
+ Use icon-only variants when the icons are intuitive and easy to understand.
44
+
45
+ > Image: Examples of a icon-only Radio Bar with two options. In the first example with heart eyes emojis, the icons are intutive
46
+
47
+
48
+ ### Radio Bar as a menu bar
49
+ Radio Bar can be used outside the context of a form and behave like a menu `role="menubar"`. When used in this context, ensure the options are straightforward and mutually exclusive.
50
+
51
+ > Image: Examples of a Radio Bar with two options. In the first example with heart eyes emojis, the options are
52
+
53
+
54
+ ## Content
55
+
56
+ ### Be concise
57
+ Keep option labels short and concise to prevent text wrapping. Use sentence-case capitalization and avoid punctuation and articles (“the”, “an”, “a”).
58
+
59
+ > Image: Examples of a Radio Bar with two options. In the first example with heart eyes emojis, the options are
60
+
61
+
62
+ [1]: ./RadioList
63
+ [2]: ./Switch
64
+ [3]: ./TabBar
65
+ [4]: ./Select
66
+ [5]: ./ComboBox
67
+
68
+ ## Examples
69
+
70
+
71
+ ### Controlled
72
+
73
+ ```typescript
74
+ import React, { useState } from 'react';
75
+
76
+ import RadioBar, { RadioBarChangeHandler } from '@splunk/react-ui/RadioBar';
77
+
78
+
79
+ function Basic() {
80
+ const [value, setValue] = useState(3);
81
+
82
+ const handleChange: RadioBarChangeHandler = (e, { value: radioValue }) => {
83
+ setValue(radioValue);
84
+ };
85
+
86
+ return (
87
+ <RadioBar onChange={handleChange} value={value} style={{ width: 500 }}>
88
+ <RadioBar.Option value={1} label="one" />
89
+ <RadioBar.Option value={2} label="two" />
90
+ <RadioBar.Option value={3} label="threethreethree" />
91
+ <RadioBar.Option value={4} label="four" />
92
+ </RadioBar>
93
+ );
94
+ }
95
+
96
+ export default Basic;
97
+ ```
98
+
99
+
100
+
101
+ ### Uncontrolled
102
+
103
+ ```typescript
104
+ import React from 'react';
105
+
106
+ import RadioBar from '@splunk/react-ui/RadioBar';
107
+
108
+
109
+ function Uncontrolled() {
110
+ return (
111
+ <RadioBar defaultValue={2} style={{ width: 500 }}>
112
+ <RadioBar.Option value={1} label="one" />
113
+ <RadioBar.Option value={2} label="two" />
114
+ <RadioBar.Option value={3} label="threethreethree" />
115
+ <RadioBar.Option value={4} label="four" />
116
+ </RadioBar>
117
+ );
118
+ }
119
+
120
+ export default Uncontrolled;
121
+ ```
122
+
123
+
124
+
125
+ ### Error
126
+
127
+ ```typescript
128
+ import React from 'react';
129
+
130
+ import RadioBar from '@splunk/react-ui/RadioBar';
131
+
132
+
133
+ function RadioBarError() {
134
+ return (
135
+ <RadioBar defaultValue={2} style={{ width: 500 }} error>
136
+ <RadioBar.Option value={1} label="one" />
137
+ <RadioBar.Option value={2} label="two" />
138
+ <RadioBar.Option value={3} label="threethreethree" />
139
+ <RadioBar.Option value={4} label="four" />
140
+ </RadioBar>
141
+ );
142
+ }
143
+
144
+ export default RadioBarError;
145
+ ```
146
+
147
+
148
+
149
+ ### Disabled
150
+
151
+ Either the entire RadioBar or individual Options can be disabled using the disabled prop. When set on the RadioBar, this overrides any individual Option disabled states.
152
+
153
+ ```typescript
154
+ import React from 'react';
155
+
156
+ import RadioBar from '@splunk/react-ui/RadioBar';
157
+
158
+
159
+ function Disabled() {
160
+ return (
161
+ <RadioBar defaultValue={2} disabled style={{ width: 500 }}>
162
+ <RadioBar.Option value={1} label="one" />
163
+ <RadioBar.Option value={2} label="two" />
164
+ <RadioBar.Option value={3} label="threethreethree" />
165
+ <RadioBar.Option value={4} label="four" />
166
+ </RadioBar>
167
+ );
168
+ }
169
+
170
+ export default Disabled;
171
+ ```
172
+
173
+
174
+
175
+ ### Adornments using `aria-*` attributes
176
+
177
+ ```typescript
178
+ import React from 'react';
179
+
180
+ import styled from 'styled-components';
181
+
182
+ import ChartArea from '@splunk/react-icons/ChartArea';
183
+ import ChartBubble from '@splunk/react-icons/ChartBubble';
184
+ import ChartLine from '@splunk/react-icons/ChartLine';
185
+ import Plus from '@splunk/react-icons/Plus';
186
+ import Chip from '@splunk/react-ui/Chip';
187
+ import RadioBar from '@splunk/react-ui/RadioBar';
188
+ import { mixins, variables } from '@splunk/themes';
189
+
190
+ const StyledNewChip = styled(Chip)`
191
+ ${mixins.typography('smallBody', { weight: 'bold' })}
192
+ background-color: ${variables.notificationColorInfoWeak};
193
+ height: calc(${variables.inputHeight} - ${variables.spacingMedium});
194
+ `;
195
+
196
+
197
+ function AdornmentAriaExamples() {
198
+ return (
199
+ <RadioBar defaultValue={3} style={{ width: 800 }}>
200
+ <RadioBar.Option value={1} label="Option one" endAdornment={<ChartLine />} />
201
+ <RadioBar.Option value={2} label="Option two" startAdornment={<ChartBubble />} />
202
+
203
+ <RadioBar.Option
204
+ value={3}
205
+ label="Option three"
206
+ aria-describedby="new"
207
+ endAdornment={<StyledNewChip id="new">New</StyledNewChip>}
208
+ />
209
+
210
+ <RadioBar.Option
211
+ value={4}
212
+ label="Option four"
213
+ startAdornment={<Plus />}
214
+ endAdornment={<ChartArea />}
215
+ />
216
+ </RadioBar>
217
+ );
218
+ }
219
+
220
+ export default AdornmentAriaExamples;
221
+ ```
222
+
223
+
224
+
225
+ ### menubar
226
+
227
+ Radio Bar can be used outside of a form context to behave like a menu bar by setting role="menubar"
228
+
229
+ ```typescript
230
+ import React, { useState } from 'react';
231
+
232
+ import RadioBar, { RadioBarChangeHandler } from '@splunk/react-ui/RadioBar';
233
+
234
+
235
+ function MenuBar() {
236
+ const [value, setValue] = useState('ts');
237
+
238
+ const handleChange: RadioBarChangeHandler = (e, { value: radioValue }) => {
239
+ setValue(radioValue);
240
+ };
241
+
242
+ return (
243
+ <RadioBar role="menubar" onChange={handleChange} value={value}>
244
+ <RadioBar.Option value="ts" label="Typescript" />
245
+ <RadioBar.Option value="js" label="Javascript" />
246
+ </RadioBar>
247
+ );
248
+ }
249
+
250
+ export default MenuBar;
251
+ ```
252
+
253
+
254
+
255
+
256
+ ## API
257
+
258
+
259
+ ### RadioBar API
260
+
261
+ RadioBar is a form control that provides the ability to select one option out of a group.
262
+
263
+ #### Props
264
+
265
+ | Name | Type | Required | Default | Description |
266
+ |------|------|------|------|------|
267
+ | children | React.ReactNode | no | | `children` should be `RadioBar.Option`. |
268
+ | defaultValue | string \| number \| boolean | no | | The default value. Only applicable if this is an uncontrolled component. Otherwise, use the value prop. |
269
+ | describedBy | string | no | | The id of the description. When placed in a ControlGroup, this is automatically set to the ControlGroup's help component. |
270
+ | disabled | boolean | no | false | Disable all options in the RadioBar. This will override the disabled prop on any individual Option. |
271
+ | elementRef | React.Ref<HTMLDivElement> | no | | A React ref which is set to the DOM element when the component mounts, and null when it unmounts. |
272
+ | error | boolean | no | | Highlight the field as having an error. The buttons will turn red. |
273
+ | inline | boolean | no | | |
274
+ | labelledBy | string | no | | The id of the label. When placed in a ControlGroup, this is automatically set to the ControlGroup's label. |
275
+ | name | string | no | | The name is returned with onChange events, which can be used to identify the control when multiple controls share an onChange callback. |
276
+ | onChange | RadioBarChangeHandler | no | | A callback that receives the new value. |
277
+ | role | 'radiogroup' \| 'menubar' | no | 'radiogroup' | The role of the RadioBar. The children Options' `role` will be set to `radio` or `menuitemradio` respectively. |
278
+ | value | string \| number \| boolean | no | | The currently selected value. Only applicable if this is a controlled component. |
279
+
280
+ #### Types
281
+
282
+ | Name | Type | Description |
283
+ |------|------|------|
284
+ | RadioBarChangeHandler | ( e: React.MouseEvent<HTMLButtonElement \| HTMLAnchorElement> \| React.KeyboardEvent<HTMLElement>, data: { label?: string; name?: string; value: any; // eslint-disable-line @typescript-eslint/no-explicit-any } ) => void | |
285
+
286
+
287
+
288
+ ### RadioBar.Option API
289
+
290
+ #### Props
291
+
292
+ | Name | Type | Required | Default | Description |
293
+ |------|------|------|------|------|
294
+ | disabled | boolean | no | | Add a disabled attribute and prevent clicking. |
295
+ | endAdornment | React.ReactNode | no | | Adornment after the label. |
296
+ | label | string | no | | The text shown on the button. |
297
+ | startAdornment | React.ReactNode | no | | Adornment in front of the label. |
298
+ | value | any | yes | | The value of the `Option`. |
299
+
300
+
301
+
302
+
303
+