@dxc-technology/halstack-react 8.0.0 → 9.0.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 (88) hide show
  1. package/HalstackContext.js +94 -45
  2. package/accordion/Accordion.js +7 -13
  3. package/accordion/Accordion.stories.tsx +102 -13
  4. package/alert/Alert.stories.tsx +28 -0
  5. package/box/Box.js +1 -3
  6. package/box/Box.stories.tsx +15 -0
  7. package/button/Button.js +11 -13
  8. package/button/Button.stories.tsx +150 -8
  9. package/checkbox/Checkbox.stories.tsx +52 -0
  10. package/chip/Chip.js +16 -22
  11. package/chip/Chip.stories.tsx +96 -9
  12. package/common/variables.js +280 -288
  13. package/date-input/Calendar.d.ts +1 -1
  14. package/date-input/Calendar.js +43 -43
  15. package/date-input/DateInput.js +74 -32
  16. package/date-input/DateInput.stories.tsx +183 -30
  17. package/date-input/DateInput.test.js +120 -37
  18. package/date-input/DatePicker.js +38 -52
  19. package/date-input/Icons.d.ts +6 -0
  20. package/date-input/Icons.js +75 -0
  21. package/date-input/YearPicker.d.ts +1 -1
  22. package/date-input/YearPicker.js +23 -12
  23. package/date-input/types.d.ts +6 -8
  24. package/dialog/Dialog.js +60 -73
  25. package/dialog/Dialog.stories.tsx +211 -159
  26. package/dialog/Dialog.test.js +301 -2
  27. package/dropdown/Dropdown.js +3 -6
  28. package/dropdown/Dropdown.stories.tsx +210 -84
  29. package/dropdown/DropdownMenu.js +8 -18
  30. package/dropdown/DropdownMenuItem.js +4 -15
  31. package/file-input/FileInput.js +3 -6
  32. package/file-input/FileInput.stories.tsx +85 -2
  33. package/file-input/FileInput.test.js +0 -41
  34. package/file-input/FileItem.js +1 -0
  35. package/footer/Footer.stories.tsx +91 -0
  36. package/header/Header.js +18 -20
  37. package/header/Header.stories.tsx +149 -6
  38. package/link/Link.stories.tsx +60 -0
  39. package/main.d.ts +1 -1
  40. package/main.js +1 -1
  41. package/{tabs-nav → nav-tabs}/NavTabs.js +1 -1
  42. package/{tabs-nav → nav-tabs}/NavTabs.stories.tsx +96 -6
  43. package/{tabs-nav → nav-tabs}/Tab.js +35 -15
  44. package/package.json +1 -1
  45. package/paginator/Icons.d.ts +5 -0
  46. package/paginator/Icons.js +16 -28
  47. package/paginator/Paginator.js +5 -11
  48. package/paginator/Paginator.stories.tsx +24 -0
  49. package/paginator/Paginator.test.js +17 -10
  50. package/progress-bar/ProgressBar.js +4 -4
  51. package/progress-bar/ProgressBar.stories.jsx +35 -2
  52. package/quick-nav/QuickNav.stories.tsx +14 -0
  53. package/radio-group/RadioGroup.stories.tsx +131 -18
  54. package/resultsetTable/ResultsetTable.test.js +17 -22
  55. package/select/Listbox.d.ts +1 -1
  56. package/select/Listbox.js +5 -34
  57. package/select/Option.js +11 -24
  58. package/select/Select.js +43 -24
  59. package/select/Select.stories.tsx +492 -145
  60. package/select/Select.test.js +17 -22
  61. package/select/types.d.ts +2 -2
  62. package/sidenav/Sidenav.js +8 -10
  63. package/sidenav/Sidenav.stories.tsx +148 -46
  64. package/slider/Slider.js +4 -4
  65. package/slider/Slider.stories.tsx +57 -0
  66. package/spinner/Spinner.js +2 -2
  67. package/spinner/Spinner.stories.jsx +27 -1
  68. package/switch/Switch.js +1 -1
  69. package/switch/Switch.stories.tsx +33 -0
  70. package/table/Table.stories.jsx +80 -1
  71. package/tabs/Tab.js +3 -5
  72. package/tabs/Tabs.js +3 -3
  73. package/tabs/Tabs.stories.tsx +45 -5
  74. package/tag/Tag.stories.tsx +14 -1
  75. package/text-input/Suggestion.js +32 -5
  76. package/text-input/TextInput.js +7 -11
  77. package/text-input/TextInput.stories.tsx +92 -4
  78. package/text-input/TextInput.test.js +125 -25
  79. package/textarea/Textarea.stories.jsx +60 -1
  80. package/toggle-group/ToggleGroup.stories.tsx +42 -0
  81. package/utils/FocusLock.d.ts +13 -0
  82. package/utils/FocusLock.js +139 -0
  83. package/wizard/Wizard.stories.tsx +20 -0
  84. /package/{tabs-nav → nav-tabs}/NavTabs.d.ts +0 -0
  85. /package/{tabs-nav → nav-tabs}/NavTabs.test.js +0 -0
  86. /package/{tabs-nav → nav-tabs}/Tab.d.ts +0 -0
  87. /package/{tabs-nav → nav-tabs}/types.d.ts +0 -0
  88. /package/{tabs-nav → nav-tabs}/types.js +0 -0
@@ -57,6 +57,7 @@ global.DOMRect = {
57
57
  }
58
58
  };
59
59
  var countries = ["Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Antigua and Barbuda", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands, The", "Central African Republic", "Chad", "Democratic Republic of the Congo", "Dominican Republic", "Dominica", "Denmark", "Djibouti"];
60
+ var specialCharacters = ["/", "\\", "*", "(", ")", "[", "]", "+", "?", "*{[]}|"];
60
61
  describe("TextInput component tests", function () {
61
62
  test("Renders with correct error aria attributes", function () {
62
63
  var _render = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
@@ -1183,10 +1184,109 @@ describe("TextInput component synchronous autosuggest tests", function () {
1183
1184
  expect(input.value).toBe("");
1184
1185
  expect(queryByRole("listbox")).toBeFalsy();
1185
1186
  });
1187
+ test("Autosuggest escapes special characters", function () {
1188
+ var onChange = jest.fn();
1189
+
1190
+ var _render37 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1191
+ label: "Autocomplete Countries",
1192
+ suggestions: specialCharacters,
1193
+ onChange: onChange
1194
+ })),
1195
+ getAllByText = _render37.getAllByText,
1196
+ getByText = _render37.getByText,
1197
+ getByRole = _render37.getByRole;
1198
+
1199
+ var input = getByRole("combobox");
1200
+
1201
+ _react2.fireEvent.focus(input);
1202
+
1203
+ var list = getByRole("listbox");
1204
+
1205
+ _react2.fireEvent.change(input, {
1206
+ target: {
1207
+ value: "/"
1208
+ }
1209
+ });
1210
+
1211
+ expect(list).toBeTruthy();
1212
+ expect(getAllByText("/").length).toBe(1);
1213
+
1214
+ _react2.fireEvent.change(input, {
1215
+ target: {
1216
+ value: "\\"
1217
+ }
1218
+ });
1219
+
1220
+ expect(list).toBeTruthy();
1221
+ expect(getAllByText("\\").length).toBe(1);
1222
+
1223
+ _react2.fireEvent.change(input, {
1224
+ target: {
1225
+ value: "*"
1226
+ }
1227
+ });
1228
+
1229
+ expect(list).toBeTruthy();
1230
+ expect(getAllByText("*").length).toBe(2);
1231
+
1232
+ _react2.fireEvent.change(input, {
1233
+ target: {
1234
+ value: "("
1235
+ }
1236
+ });
1237
+
1238
+ expect(list).toBeTruthy();
1239
+ expect(getAllByText("(").length).toBe(1);
1240
+
1241
+ _react2.fireEvent.change(input, {
1242
+ target: {
1243
+ value: ")"
1244
+ }
1245
+ });
1246
+
1247
+ expect(list).toBeTruthy();
1248
+ expect(getAllByText(")").length).toBe(1);
1249
+
1250
+ _react2.fireEvent.change(input, {
1251
+ target: {
1252
+ value: "["
1253
+ }
1254
+ });
1255
+
1256
+ expect(list).toBeTruthy();
1257
+ expect(getAllByText("[").length).toBe(1);
1258
+
1259
+ _react2.fireEvent.change(input, {
1260
+ target: {
1261
+ value: "]"
1262
+ }
1263
+ });
1264
+
1265
+ expect(list).toBeTruthy();
1266
+ expect(getAllByText("]").length).toBe(1);
1267
+
1268
+ _react2.fireEvent.change(input, {
1269
+ target: {
1270
+ value: "+"
1271
+ }
1272
+ });
1273
+
1274
+ expect(list).toBeTruthy();
1275
+ expect(getAllByText("+").length).toBe(1);
1276
+
1277
+ _react2.fireEvent.change(input, {
1278
+ target: {
1279
+ value: "?"
1280
+ }
1281
+ });
1282
+
1283
+ expect(list).toBeTruthy();
1284
+ expect(getAllByText("?").length).toBe(1);
1285
+ });
1186
1286
  });
1187
1287
  describe("TextInput component asynchronous autosuggest tests", function () {
1188
1288
  test("Autosuggest 'Searching...' message is shown", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() {
1189
- var callbackFunc, onChange, _render37, getByRole, getByText, input;
1289
+ var callbackFunc, onChange, _render38, getByRole, getByText, input;
1190
1290
 
1191
1291
  return _regenerator["default"].wrap(function _callee$(_context) {
1192
1292
  while (1) {
@@ -1203,11 +1303,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1203
1303
  return result;
1204
1304
  });
1205
1305
  onChange = jest.fn();
1206
- _render37 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1306
+ _render38 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1207
1307
  label: "Autosuggest Countries",
1208
1308
  suggestions: callbackFunc,
1209
1309
  onChange: onChange
1210
- })), getByRole = _render37.getByRole, getByText = _render37.getByText;
1310
+ })), getByRole = _render38.getByRole, getByText = _render38.getByText;
1211
1311
  input = getByRole("combobox");
1212
1312
 
1213
1313
  _react2.fireEvent.focus(input);
@@ -1270,14 +1370,14 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1270
1370
  });
1271
1371
  var onChange = jest.fn();
1272
1372
 
1273
- var _render38 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1373
+ var _render39 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1274
1374
  label: "Autosuggest Countries",
1275
1375
  suggestions: callbackFunc,
1276
1376
  onChange: onChange
1277
1377
  })),
1278
- getByRole = _render38.getByRole,
1279
- queryByText = _render38.queryByText,
1280
- queryByRole = _render38.queryByRole;
1378
+ getByRole = _render39.getByRole,
1379
+ queryByText = _render39.queryByText,
1380
+ queryByRole = _render39.queryByRole;
1281
1381
 
1282
1382
  var input = getByRole("combobox");
1283
1383
 
@@ -1299,7 +1399,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1299
1399
  expect(input.value).toBe("");
1300
1400
  });
1301
1401
  test("Autosuggest Esc + arrow down working while 'Searching...' message is shown", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() {
1302
- var callbackFunc, onChange, _render39, getByRole, getByText, queryByText, queryByRole, input, list;
1402
+ var callbackFunc, onChange, _render40, getByRole, getByText, queryByText, queryByRole, input, list;
1303
1403
 
1304
1404
  return _regenerator["default"].wrap(function _callee2$(_context2) {
1305
1405
  while (1) {
@@ -1316,11 +1416,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1316
1416
  return result;
1317
1417
  });
1318
1418
  onChange = jest.fn();
1319
- _render39 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1419
+ _render40 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1320
1420
  label: "Autosuggest Countries",
1321
1421
  suggestions: callbackFunc,
1322
1422
  onChange: onChange
1323
- })), getByRole = _render39.getByRole, getByText = _render39.getByText, queryByText = _render39.queryByText, queryByRole = _render39.queryByRole;
1423
+ })), getByRole = _render40.getByRole, getByText = _render40.getByText, queryByText = _render40.queryByText, queryByRole = _render40.queryByRole;
1324
1424
  input = getByRole("combobox");
1325
1425
 
1326
1426
  _react2.fireEvent.focus(input);
@@ -1368,7 +1468,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1368
1468
  }, _callee2);
1369
1469
  })));
1370
1470
  test("Asynchronous uncontrolled autosuggest test", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() {
1371
- var callbackFunc, onChange, _render40, getByRole, getByText, input;
1471
+ var callbackFunc, onChange, _render41, getByRole, getByText, input;
1372
1472
 
1373
1473
  return _regenerator["default"].wrap(function _callee3$(_context3) {
1374
1474
  while (1) {
@@ -1385,11 +1485,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1385
1485
  return result;
1386
1486
  });
1387
1487
  onChange = jest.fn();
1388
- _render40 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1488
+ _render41 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1389
1489
  label: "Autosuggest Countries",
1390
1490
  onChange: onChange,
1391
1491
  suggestions: callbackFunc
1392
- })), getByRole = _render40.getByRole, getByText = _render40.getByText;
1492
+ })), getByRole = _render41.getByRole, getByText = _render41.getByText;
1393
1493
  input = getByRole("combobox");
1394
1494
 
1395
1495
  _react2.fireEvent.focus(input);
@@ -1419,7 +1519,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1419
1519
  }, _callee3);
1420
1520
  })));
1421
1521
  test("Asynchronous controlled autosuggest test", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4() {
1422
- var callbackFunc, onChange, _render41, getByRole, getByText, queryByRole, input;
1522
+ var callbackFunc, onChange, _render42, getByRole, getByText, queryByRole, input;
1423
1523
 
1424
1524
  return _regenerator["default"].wrap(function _callee4$(_context4) {
1425
1525
  while (1) {
@@ -1436,12 +1536,12 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1436
1536
  return result;
1437
1537
  });
1438
1538
  onChange = jest.fn();
1439
- _render41 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1539
+ _render42 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1440
1540
  label: "Autosuggest Countries",
1441
1541
  value: "Denm",
1442
1542
  onChange: onChange,
1443
1543
  suggestions: callbackFunc
1444
- })), getByRole = _render41.getByRole, getByText = _render41.getByText, queryByRole = _render41.queryByRole;
1544
+ })), getByRole = _render42.getByRole, getByText = _render42.getByText, queryByRole = _render42.queryByRole;
1445
1545
  input = getByRole("combobox");
1446
1546
  expect(input.value).toBe("Denm");
1447
1547
 
@@ -1472,7 +1572,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1472
1572
  }, _callee4);
1473
1573
  })));
1474
1574
  test("Asynchronous autosuggest closes the listbox after finishing no matches search", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5() {
1475
- var callbackFunc, onChange, _render42, getByText, getByRole, queryByRole, input;
1575
+ var callbackFunc, onChange, _render43, getByText, getByRole, queryByRole, input;
1476
1576
 
1477
1577
  return _regenerator["default"].wrap(function _callee5$(_context5) {
1478
1578
  while (1) {
@@ -1489,11 +1589,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1489
1589
  return result;
1490
1590
  });
1491
1591
  onChange = jest.fn();
1492
- _render42 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1592
+ _render43 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1493
1593
  label: "Autosuggest Countries",
1494
1594
  onChange: onChange,
1495
1595
  suggestions: callbackFunc
1496
- })), getByText = _render42.getByText, getByRole = _render42.getByRole, queryByRole = _render42.queryByRole;
1596
+ })), getByText = _render43.getByText, getByRole = _render43.getByRole, queryByRole = _render43.queryByRole;
1497
1597
  input = getByRole("combobox");
1498
1598
 
1499
1599
  _react2.fireEvent.focus(input);
@@ -1516,7 +1616,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1516
1616
  }, _callee5);
1517
1617
  })));
1518
1618
  test("Asynchronous autosuggest with no matches founded doesn't let the listbox to be opened", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6() {
1519
- var callbackFunc, onChange, _render43, getByText, getByRole, queryByRole, input;
1619
+ var callbackFunc, onChange, _render44, getByText, getByRole, queryByRole, input;
1520
1620
 
1521
1621
  return _regenerator["default"].wrap(function _callee6$(_context6) {
1522
1622
  while (1) {
@@ -1533,11 +1633,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1533
1633
  return result;
1534
1634
  });
1535
1635
  onChange = jest.fn();
1536
- _render43 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1636
+ _render44 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1537
1637
  label: "Autosuggest Countries",
1538
1638
  onChange: onChange,
1539
1639
  suggestions: callbackFunc
1540
- })), getByText = _render43.getByText, getByRole = _render43.getByRole, queryByRole = _render43.queryByRole;
1640
+ })), getByText = _render44.getByText, getByRole = _render44.getByRole, queryByRole = _render44.queryByRole;
1541
1641
  input = getByRole("combobox");
1542
1642
 
1543
1643
  _react2.fireEvent.focus(input);
@@ -1582,7 +1682,7 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1582
1682
  }, _callee6);
1583
1683
  })));
1584
1684
  test("Asynchronous autosuggest request failed, shows 'Error fetching data' message", /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7() {
1585
- var errorCallbackFunc, onChange, _render44, getByRole, getByText, input;
1685
+ var errorCallbackFunc, onChange, _render45, getByRole, getByText, input;
1586
1686
 
1587
1687
  return _regenerator["default"].wrap(function _callee7$(_context7) {
1588
1688
  while (1) {
@@ -1597,11 +1697,11 @@ describe("TextInput component asynchronous autosuggest tests", function () {
1597
1697
  return result;
1598
1698
  });
1599
1699
  onChange = jest.fn();
1600
- _render44 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1700
+ _render45 = (0, _react2.render)( /*#__PURE__*/_react["default"].createElement(_TextInput["default"], {
1601
1701
  label: "Autosuggest Countries",
1602
1702
  onChange: onChange,
1603
1703
  suggestions: errorCallbackFunc
1604
- })), getByRole = _render44.getByRole, getByText = _render44.getByText;
1704
+ })), getByRole = _render45.getByRole, getByText = _render45.getByText;
1605
1705
  input = getByRole("combobox");
1606
1706
 
1607
1707
  _react2.fireEvent.focus(input);
@@ -4,12 +4,20 @@ import Title from "../../.storybook/components/Title";
4
4
  import ExampleContainer from "../../.storybook/components/ExampleContainer";
5
5
  import { BackgroundColorProvider } from "../BackgroundColorContext";
6
6
  import DarkContainer from "../../.storybook/components/DarkSection";
7
+ import { HalstackProvider } from "../HalstackContext";
7
8
 
8
9
  export default {
9
10
  title: "Textarea",
10
11
  component: DxcTextarea,
11
12
  };
12
13
 
14
+ const opinionatedTheme = {
15
+ textarea: {
16
+ fontColor: "#000000",
17
+ hoverBorderColor: "#a46ede",
18
+ },
19
+ };
20
+
13
21
  export const Chromatic = () => (
14
22
  <>
15
23
  <>
@@ -151,7 +159,58 @@ export const Chromatic = () => (
151
159
  <ExampleContainer>
152
160
  <Title title="Xxlarge margin" theme="light" level={4} />
153
161
  <DxcTextarea label="Xxlarge" margin="xxlarge" />
154
- <hr />
162
+ </ExampleContainer>
163
+ <Title title="Opinionated theme" theme="light" level={2} />
164
+ <ExampleContainer pseudoState="pseudo-hover">
165
+ <Title title="Hovered" theme="light" level={4} />
166
+ <HalstackProvider theme={opinionatedTheme}>
167
+ <DxcTextarea label="Hovered" helperText="Sample text" placeholder="Placeholder" />
168
+ </HalstackProvider>
169
+ </ExampleContainer>
170
+ <ExampleContainer pseudoState="pseudo-focus">
171
+ <Title title="Focused" theme="light" level={4} />
172
+ <HalstackProvider theme={opinionatedTheme}>
173
+ <DxcTextarea label="Focused" helperText="Sample text" />
174
+ </HalstackProvider>
175
+ </ExampleContainer>
176
+ <ExampleContainer>
177
+ <Title title="Disabled" theme="light" level={4} />
178
+ <HalstackProvider theme={opinionatedTheme}>
179
+ <DxcTextarea
180
+ label="Disabled"
181
+ optional
182
+ helperText="Sample text"
183
+ placeholder="Enter your text here..."
184
+ disabled
185
+ />
186
+ </HalstackProvider>
187
+ </ExampleContainer>
188
+ <ExampleContainer>
189
+ <Title title="Disabled with value" theme="light" level={4} />
190
+ <HalstackProvider theme={opinionatedTheme}>
191
+ <DxcTextarea label="Disabled" helperText="Sample text" defaultValue="Example text" disabled />
192
+ </HalstackProvider>
193
+ </ExampleContainer>
194
+ <ExampleContainer>
195
+ <Title title="With error" theme="light" level={4} />
196
+ <HalstackProvider theme={opinionatedTheme}>
197
+ <DxcTextarea
198
+ label="Textarea with error"
199
+ helperText="Helper text"
200
+ placeholder="Enter your text here..."
201
+ error="Error message."
202
+ />
203
+ </HalstackProvider>
204
+ </ExampleContainer>
205
+ <ExampleContainer>
206
+ <Title title="Grow manual" theme="light" level={4} />{" "}
207
+ <HalstackProvider theme={opinionatedTheme}>
208
+ <DxcTextarea
209
+ label="Manual vertical grow"
210
+ verticalGrow="manual"
211
+ defaultValue="Long textttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt"
212
+ />
213
+ </HalstackProvider>
155
214
  </ExampleContainer>
156
215
  </>
157
216
  );
@@ -3,6 +3,7 @@ import { userEvent, within } from "@storybook/testing-library";
3
3
  import DxcToggleGroup from "./ToggleGroup";
4
4
  import Title from "../../.storybook/components/Title";
5
5
  import ExampleContainer from "../../.storybook/components/ExampleContainer";
6
+ import { HalstackProvider } from "../HalstackContext";
6
7
 
7
8
  export default {
8
9
  title: "ToggleGroup",
@@ -89,6 +90,16 @@ const twoOptions = [
89
90
  label: "Twitter",
90
91
  },
91
92
  ];
93
+
94
+ const opinionatedTheme = {
95
+ toggleGroup: {
96
+ selectedBaseColor: "#5f249f",
97
+ selectedFontColor: "#ffffff",
98
+ unselectedBaseColor: "#e6e6e6",
99
+ unselectedFontColor: "#000000",
100
+ },
101
+ };
102
+
92
103
  export const Chromatic = () => (
93
104
  <>
94
105
  <ExampleContainer>
@@ -154,6 +165,37 @@ export const Chromatic = () => (
154
165
  <Title title="xxLarge" theme="light" level={4} />
155
166
  <DxcToggleGroup label="xxLarge margin" options={options} margin="xxlarge" />
156
167
  </ExampleContainer>
168
+ <Title title="Opinionated theme" theme="light" level={2} />
169
+ <ExampleContainer>
170
+ <HalstackProvider theme={opinionatedTheme}>
171
+ <Title title="Selected" theme="light" level={4} />
172
+ <DxcToggleGroup label="Selected" helperText="HelperText" defaultValue={2} options={options} />
173
+ </HalstackProvider>
174
+ </ExampleContainer>
175
+ <ExampleContainer>
176
+ <HalstackProvider theme={opinionatedTheme}>
177
+ <Title title="Icons & label toggle group" theme="light" level={4} />
178
+ <DxcToggleGroup label="Icons & label" options={optionsWithIconAndLabel} />
179
+ </HalstackProvider>
180
+ </ExampleContainer>
181
+ <ExampleContainer>
182
+ <HalstackProvider theme={opinionatedTheme}>
183
+ <Title title="Disabled" theme="light" level={4} />
184
+ <DxcToggleGroup label="Disabled" defaultValue={2} options={options} disabled />
185
+ </HalstackProvider>
186
+ </ExampleContainer>
187
+ <ExampleContainer pseudoState="pseudo-hover">
188
+ <Title title="Hovered" theme="light" level={4} />
189
+ <HalstackProvider theme={opinionatedTheme}>
190
+ <DxcToggleGroup label="Hovered" options={twoOptions} defaultValue={2} />
191
+ </HalstackProvider>
192
+ </ExampleContainer>
193
+ <ExampleContainer pseudoState="pseudo-active">
194
+ <Title title="Actived" theme="light" level={4} />
195
+ <HalstackProvider theme={opinionatedTheme}>
196
+ <DxcToggleGroup label="Actived" options={twoOptions} defaultValue={2} />
197
+ </HalstackProvider>
198
+ </ExampleContainer>
157
199
  </>
158
200
  );
159
201
  const OptionSelected = () => <DxcToggleGroup label="Toggle group" helperText="HelperText" options={options} />;
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ /**
3
+ * Traps the focus inside the children of the component. It will focus the first focusable element when the component is mounted.
4
+ * When the focus is on the last focusable element and the user tries to focus the next element, it will focus the first element.
5
+ * When the focus is on the first focusable element and the user tries to focus the previous element, it will focus the last element.
6
+ * The focus can't be moved outside the children unless the children are removed from the DOM (for example, a Dialog, a Modal, etc).
7
+ * @param children: React.ReactNode
8
+ * @returns
9
+ */
10
+ declare const FocusLock: ({ children }: {
11
+ children: React.ReactNode;
12
+ }) => JSX.Element;
13
+ export default FocusLock;
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _typeof = require("@babel/runtime/helpers/typeof");
6
+
7
+ Object.defineProperty(exports, "__esModule", {
8
+ value: true
9
+ });
10
+ exports["default"] = void 0;
11
+
12
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
13
+
14
+ var _react = _interopRequireWildcard(require("react"));
15
+
16
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
+
18
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+
20
+ var not = {
21
+ inert: ":not([inert]):not([inert] *)",
22
+ negTabIndex: ':not([tabindex^="-"])',
23
+ disabled: ":not(:disabled):not([aria-disabled='true'])"
24
+ };
25
+ var focusableQuery = ["a[href]".concat(not.inert).concat(not.negTabIndex), "area[href]".concat(not.inert).concat(not.negTabIndex), "input:not([type=\"hidden\"])".concat(not.inert).concat(not.negTabIndex).concat(not.disabled), "select".concat(not.inert).concat(not.negTabIndex).concat(not.disabled), "textarea".concat(not.inert).concat(not.negTabIndex).concat(not.disabled), "button".concat(not.inert).concat(not.negTabIndex).concat(not.disabled), "details".concat(not.inert, " > summary:first-of-type").concat(not.negTabIndex), "iframe".concat(not.inert).concat(not.negTabIndex), "audio[controls]".concat(not.inert).concat(not.negTabIndex), "video[controls]".concat(not.inert).concat(not.negTabIndex), "[contenteditable]".concat(not.inert).concat(not.negTabIndex), "[tabindex]".concat(not.inert).concat(not.negTabIndex).concat(not.disabled)].join(",");
26
+
27
+ var getFocusableElements = function getFocusableElements(container) {
28
+ return Array.prototype.slice.call(container.querySelectorAll(focusableQuery)).filter(function (element) {
29
+ return element.getAttribute("aria-hidden") !== "true" && window.getComputedStyle(element).display !== "none" && window.getComputedStyle(element).visibility !== "hidden";
30
+ });
31
+ };
32
+ /**
33
+ * This function will try to focus the element and return true if it was able to receive the focus.
34
+ * Even if the element is focusable (passes any of the conditions of our selector), there is the possibility
35
+ * that the element may not be focusable at all.
36
+ * @param element: HTMLElement
37
+ * @returns
38
+ */
39
+
40
+
41
+ var attempFocus = function attempFocus(element) {
42
+ element === null || element === void 0 ? void 0 : element.focus();
43
+ return document.activeElement === element;
44
+ };
45
+ /**
46
+ * @param element: HTMLElement
47
+ * @returns boolean: true if element is contained inside a Radix Portal, false otherwise.
48
+ */
49
+
50
+
51
+ var radixPortalContains = function radixPortalContains(activeElement) {
52
+ var radixPortals = document.querySelectorAll("[data-radix-portal]");
53
+ return Array.prototype.slice.call(radixPortals).some(function (portal) {
54
+ return portal.contains(activeElement);
55
+ });
56
+ };
57
+ /**
58
+ * Custom hook that returns an array of focusable elements inside a container.
59
+ * @param ref: React.MutableRefObject<HTMLDivElement>
60
+ * @returns
61
+ */
62
+
63
+
64
+ var useFocusableElements = function useFocusableElements(ref) {
65
+ var _useState = (0, _react.useState)(),
66
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
67
+ focusableElements = _useState2[0],
68
+ setFocusableElements = _useState2[1];
69
+
70
+ (0, _react.useEffect)(function () {
71
+ if (ref.current != null) {
72
+ setFocusableElements(getFocusableElements(ref.current));
73
+ var observer = new MutationObserver(function () {
74
+ setFocusableElements(getFocusableElements(ref.current));
75
+ });
76
+ observer.observe(ref.current, {
77
+ childList: true,
78
+ subtree: true,
79
+ attributes: true
80
+ });
81
+ return function () {
82
+ observer.disconnect();
83
+ };
84
+ }
85
+ }, []);
86
+ return focusableElements;
87
+ };
88
+ /**
89
+ * Traps the focus inside the children of the component. It will focus the first focusable element when the component is mounted.
90
+ * When the focus is on the last focusable element and the user tries to focus the next element, it will focus the first element.
91
+ * When the focus is on the first focusable element and the user tries to focus the previous element, it will focus the last element.
92
+ * The focus can't be moved outside the children unless the children are removed from the DOM (for example, a Dialog, a Modal, etc).
93
+ * @param children: React.ReactNode
94
+ * @returns
95
+ */
96
+
97
+
98
+ var FocusLock = function FocusLock(_ref) {
99
+ var children = _ref.children;
100
+ var childrenContainerRef = (0, _react.useRef)();
101
+ var focusableElements = useFocusableElements(childrenContainerRef);
102
+ var focusFirst = (0, _react.useCallback)(function () {
103
+ var _childrenContainerRef;
104
+
105
+ if ((focusableElements === null || focusableElements === void 0 ? void 0 : focusableElements.length) === 0) (_childrenContainerRef = childrenContainerRef.current) === null || _childrenContainerRef === void 0 ? void 0 : _childrenContainerRef.focus();else if ((focusableElements === null || focusableElements === void 0 ? void 0 : focusableElements.length) > 0) for (var i = 0; i < focusableElements.length; i++) {
106
+ if (attempFocus(focusableElements[i])) return;
107
+ }
108
+ }, [focusableElements]);
109
+
110
+ var focusLast = function focusLast() {
111
+ for (var i = focusableElements.length - 1; i >= 0; i--) {
112
+ if (attempFocus(focusableElements[i])) return;
113
+ }
114
+ };
115
+
116
+ var focusLock = function focusLock(event) {
117
+ if (event.key === "Tab") focusableElements.length === 0 && event.preventDefault();else if (event.key === "Tab" && event.key === "Shift") focusableElements.length === 0 && event.preventDefault();
118
+ };
119
+
120
+ (0, _react.useEffect)(function () {
121
+ var _childrenContainerRef2;
122
+
123
+ if (!((_childrenContainerRef2 = childrenContainerRef.current) !== null && _childrenContainerRef2 !== void 0 && _childrenContainerRef2.contains(document.activeElement)) && !radixPortalContains(document.activeElement)) focusFirst();
124
+ }, [focusFirst]);
125
+ return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("div", {
126
+ onFocus: focusLast,
127
+ tabIndex: 0
128
+ }), /*#__PURE__*/_react["default"].createElement("div", {
129
+ onKeyDown: focusLock,
130
+ ref: childrenContainerRef,
131
+ tabIndex: (focusableElements === null || focusableElements === void 0 ? void 0 : focusableElements.length) === 0 ? 0 : -1
132
+ }, children), /*#__PURE__*/_react["default"].createElement("div", {
133
+ onFocus: focusFirst,
134
+ tabIndex: 0
135
+ }));
136
+ };
137
+
138
+ var _default = FocusLock;
139
+ exports["default"] = _default;
@@ -3,6 +3,7 @@ import DxcWizard from "./Wizard";
3
3
  import Title from "../../.storybook/components/Title";
4
4
  import ExampleContainer from "../../.storybook/components/ExampleContainer";
5
5
  import { userEvent, within } from "@storybook/testing-library";
6
+ import { HalstackProvider } from "../HalstackContext";
6
7
 
7
8
  export default {
8
9
  title: "Wizard",
@@ -36,6 +37,7 @@ const stepWithLabel = [
36
37
  label: "Forth step",
37
38
  },
38
39
  ];
40
+
39
41
  const stepWithLabelDescription = [
40
42
  {
41
43
  label: "First step",
@@ -56,6 +58,7 @@ const stepWithLabelDescription = [
56
58
  valid: false,
57
59
  },
58
60
  ];
61
+
59
62
  const stepWithLongDescription = [
60
63
  {
61
64
  label: "First step",
@@ -73,6 +76,7 @@ const stepWithLongDescription = [
73
76
  "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ",
74
77
  },
75
78
  ];
79
+
76
80
  const stepDisabled = [
77
81
  {
78
82
  label: "First step",
@@ -98,6 +102,7 @@ const stepDisabled = [
98
102
  disabled: true,
99
103
  },
100
104
  ];
105
+
101
106
  const stepIcons = [
102
107
  {
103
108
  label: "First step",
@@ -112,6 +117,7 @@ const stepIcons = [
112
117
  icon: favoriteSVG,
113
118
  },
114
119
  ];
120
+
115
121
  const stepLargeIcons = [
116
122
  {
117
123
  label: "First step",
@@ -127,6 +133,14 @@ const stepLargeIcons = [
127
133
  },
128
134
  ];
129
135
 
136
+ const opinionatedTheme = {
137
+ wizard: {
138
+ baseColor: "#5f249f",
139
+ fontColor: "#000000",
140
+ selectedStepFontColor: "#ffffff",
141
+ },
142
+ };
143
+
130
144
  export const Chromatic = () => (
131
145
  <>
132
146
  <ExampleContainer>
@@ -215,6 +229,12 @@ export const Chromatic = () => (
215
229
  <Title title="Xxlarge margin" theme="light" level={4} />
216
230
  <DxcWizard mode="vertical" margin="xxlarge" steps={stepWithLabel}></DxcWizard>
217
231
  </ExampleContainer>
232
+ <Title title="Opinionated theme" theme="light" level={2} />
233
+ <ExampleContainer>
234
+ <HalstackProvider theme={opinionatedTheme}>
235
+ <DxcWizard defaultCurrentStep={2} steps={stepWithLabelDescription}></DxcWizard>
236
+ </HalstackProvider>
237
+ </ExampleContainer>
218
238
  </>
219
239
  );
220
240
 
File without changes
File without changes
File without changes
File without changes
File without changes