@canonical/react-components 3.8.2 → 3.9.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.
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # React components for Vanilla Framework
2
+
2
3
  ![CI](https://github.com/canonical/react-components/workflows/CI/badge.svg?branch=main)
3
4
 
4
5
  This is a collection of components designed to be the way to consume [Vanilla Framework](http://vanillaframework.io) when using React. The library exposes both a CJS and an ESM build.
@@ -33,9 +34,7 @@ Please file any issues at [GitHub](https://github.com/canonical/react-components
33
34
  You might want to:
34
35
 
35
36
  - [View the source](https://github.com/canonical/react-components) on GitHub.
36
- - Read about [developing components](https://github.com/canonical/react-components/blob/main/HACKING.md).
37
- - Find out how to [publish to NPM](https://github.com/canonical/react-components/blob/main/PUBLISH-NPM-PACKAGE.md).
38
- - Know how to [publish the docs](https://github.com/canonical/react-components/blob/main/PUBLISHING-DOCS.md) to GitHub Pages.
37
+ - Read about [developing components](HACKING.md).
39
38
 
40
39
  ## Developing locally using this repository
41
40
 
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { MouseEventHandler } from "react";
2
2
  import type { ButtonHTMLAttributes, ReactNode } from "react";
3
3
  import type { ButtonProps } from "../Button";
4
4
  import type { ClassName, PropsWithSpread } from "../../types";
@@ -33,6 +33,10 @@ export type Props = PropsWithSpread<{
33
33
  * Whether the button should be in the loading state.
34
34
  */
35
35
  loading?: boolean;
36
+ /**
37
+ * Function for handling button click event.
38
+ */
39
+ onClick?: MouseEventHandler<HTMLButtonElement>;
36
40
  /**
37
41
  * Whether the button should be in the success state.
38
42
  */
@@ -45,5 +49,5 @@ export type Props = PropsWithSpread<{
45
49
  * [Button](?path=/docs/components-button--docs) in addition to those in the
46
50
  * props table:
47
51
  */
48
- declare const ActionButton: ({ appearance, children, className, disabled, inline, loading, success, ...buttonProps }: Props) => React.JSX.Element;
52
+ declare const ActionButton: ({ appearance, children, className, onClick, disabled, inline, loading, success, ...buttonProps }: Props) => React.JSX.Element;
49
53
  export default ActionButton;
@@ -30,6 +30,7 @@ const ActionButton = _ref => {
30
30
  appearance,
31
31
  children,
32
32
  className,
33
+ onClick,
33
34
  disabled = null,
34
35
  inline = false,
35
36
  loading = false,
@@ -108,8 +109,10 @@ const ActionButton = _ref => {
108
109
  "is-inline": inline
109
110
  });
110
111
  const showIcon = showLoader || showSuccess;
112
+ const isDisabled = disabled === null ? showLoader : disabled;
111
113
  const icon = showLoader && "spinner" || showSuccess && "success" || null;
112
114
  const iconLight = appearance === "positive" || appearance === "negative";
115
+ const onClickDisabled = e => e.preventDefault();
113
116
 
114
117
  // This component uses the base button element instead of the Button component
115
118
  // as the button requires a ref and Button would have to be updated to use
@@ -117,8 +120,9 @@ const ActionButton = _ref => {
117
120
  // typescript generics.
118
121
  return /*#__PURE__*/_react.default.createElement("button", _extends({
119
122
  className: buttonClasses,
120
- disabled: disabled === null ? showLoader : disabled,
121
123
  ref: ref,
124
+ onClick: isDisabled ? onClickDisabled : onClick,
125
+ "aria-disabled": isDisabled || undefined,
122
126
  style: height && width ? {
123
127
  height: "".concat(height, "px"),
124
128
  width: "".concat(width, "px")
@@ -48,6 +48,10 @@ export type Props<D extends Record<string, unknown>> = PropsWithSpread<{
48
48
  * Whether the sort by needs to be reset after each data change.
49
49
  */
50
50
  autoResetSortBy?: boolean;
51
+ /**
52
+ * This will render between the header and the content.
53
+ */
54
+ subhead?: ReactNode;
51
55
  }, HTMLProps<HTMLTableElement>>;
52
56
  /**
53
57
  This is a [React](https://reactjs.org/) component to support many table use cases.
@@ -101,5 +105,5 @@ columns = {
101
105
  };
102
106
  ```
103
107
  */
104
- declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, autoResetSortBy, ...props }: Props<D>): React.JSX.Element;
108
+ declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, autoResetSortBy, subhead, ...props }: Props<D>): React.JSX.Element;
105
109
  export default ModularTable;
@@ -111,6 +111,7 @@ function ModularTable(_ref) {
111
111
  initialSortColumn,
112
112
  initialSortDirection,
113
113
  autoResetSortBy = false,
114
+ subhead,
114
115
  ...props
115
116
  } = _ref;
116
117
  const sortBy = (0, _react.useMemo)(() => initialSortColumn ? [{
@@ -162,7 +163,7 @@ function ModularTable(_ref) {
162
163
  // Only call this if we want it to be sortable too.
163
164
  sortable && isColumnSortable(column) ? column.getSortByToggleProps({
164
165
  title: undefined
165
- }) : {}])), column.render("Header")))))), /*#__PURE__*/_react.default.createElement("tbody", getTableBodyProps(), generateRows(rows, prepareRow, getRowProps, getCellProps), showEmpty && /*#__PURE__*/_react.default.createElement(_TableRow.default, null, /*#__PURE__*/_react.default.createElement(_TableCell.default, {
166
+ }) : {}])), column.render("Header"))))), subhead), /*#__PURE__*/_react.default.createElement("tbody", getTableBodyProps(), generateRows(rows, prepareRow, getRowProps, getCellProps), showEmpty && /*#__PURE__*/_react.default.createElement(_TableRow.default, null, /*#__PURE__*/_react.default.createElement(_TableCell.default, {
166
167
  colSpan: columns.length
167
168
  }, emptyMsg)), footer && /*#__PURE__*/_react.default.createElement(_TableRow.default, null, /*#__PURE__*/_react.default.createElement(_TableCell.default, {
168
169
  colSpan: columns.length
@@ -12,6 +12,7 @@ at the start of the group. In the following example sorting the columns will
12
12
  sort the group rows, then sort the sub-rows, but the group header always comes first.
13
13
  */
14
14
  export declare const Subrows: Story;
15
+ export declare const Subheading: Story;
15
16
  /**
16
17
  Example below shows a basic `ModularTable` with `SummaryButton` component in the footer.
17
18
  ```
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.Subrows = exports.Sortable = exports.LoadMore = exports.Empty = exports.Default = void 0;
6
+ exports.default = exports.Subrows = exports.Subheading = exports.Sortable = exports.LoadMore = exports.Empty = exports.Default = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _SummaryButton = _interopRequireDefault(require("../SummaryButton"));
9
9
  var _ModularTable = _interopRequireDefault(require("./ModularTable"));
@@ -298,6 +298,101 @@ const Subrows = exports.Subrows = {
298
298
  }),
299
299
  name: "Subrows"
300
300
  };
301
+ const Subheading = exports.Subheading = {
302
+ render: () => /*#__PURE__*/_react.default.createElement(_ModularTable.default, {
303
+ getCellProps: _ref9 => {
304
+ let {
305
+ value
306
+ } = _ref9;
307
+ return {
308
+ className: value === "1 minute" ? "p-heading--5" : ""
309
+ };
310
+ }
311
+ // eslint-disable-next-line react-hooks/rules-of-hooks
312
+ ,
313
+ columns: _react.default.useMemo(() => [{
314
+ Header: "ID",
315
+ accessor: "buildId",
316
+ Cell: _ref10 => {
317
+ let {
318
+ value
319
+ } = _ref10;
320
+ return /*#__PURE__*/_react.default.createElement("a", {
321
+ href: "#test"
322
+ }, "#", value);
323
+ }
324
+ }, {
325
+ Header: "Architecture",
326
+ accessor: "arch"
327
+ }, {
328
+ Header: "Build Duration",
329
+ accessor: "duration",
330
+ className: "u-hide--small"
331
+ }, {
332
+ Header: "Result",
333
+ accessor: "result",
334
+ Cell: _ref11 => {
335
+ let {
336
+ value
337
+ } = _ref11;
338
+ switch (value) {
339
+ case "released":
340
+ return "Released";
341
+ case "failed":
342
+ return "Failed";
343
+ default:
344
+ return "Unknown";
345
+ }
346
+ },
347
+ getCellIcon: _ref12 => {
348
+ let {
349
+ value
350
+ } = _ref12;
351
+ switch (value) {
352
+ case "released":
353
+ return _Icon.ICONS.success;
354
+ case "failed":
355
+ return _Icon.ICONS.error;
356
+ default:
357
+ return false;
358
+ }
359
+ }
360
+ }, {
361
+ Header: "Build Finished",
362
+ accessor: "finished",
363
+ className: "u-align-text--right"
364
+ }], [])
365
+ // eslint-disable-next-line react-hooks/rules-of-hooks
366
+ ,
367
+ data: _react.default.useMemo(() => [{
368
+ buildId: "5432",
369
+ arch: "arm64",
370
+ duration: "5 minutes",
371
+ result: "released",
372
+ finished: "10 minutes ago"
373
+ }, {
374
+ buildId: "1234",
375
+ arch: "armhf",
376
+ duration: "5 minutes",
377
+ result: "failed",
378
+ finished: "over 1 year ago"
379
+ }, {
380
+ buildId: "1111",
381
+ arch: "test64",
382
+ duration: "1 minute",
383
+ result: "other",
384
+ finished: "ages ago"
385
+ }], []),
386
+ subhead: /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("th", {
387
+ colSpan: 5,
388
+ className: "p-text--default",
389
+ style: {
390
+ textTransform: "none"
391
+ }
392
+ }, "Showing 3 of 3 results"))
393
+ }),
394
+ name: "Subheading"
395
+ };
301
396
 
302
397
  /**
303
398
  Example below shows a basic `ModularTable` with `SummaryButton` component in the footer.
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { MouseEventHandler } from "react";
2
2
  import type { ButtonHTMLAttributes, ReactNode } from "react";
3
3
  import type { ButtonProps } from "../Button";
4
4
  import type { ClassName, PropsWithSpread } from "../../types";
@@ -33,6 +33,10 @@ export type Props = PropsWithSpread<{
33
33
  * Whether the button should be in the loading state.
34
34
  */
35
35
  loading?: boolean;
36
+ /**
37
+ * Function for handling button click event.
38
+ */
39
+ onClick?: MouseEventHandler<HTMLButtonElement>;
36
40
  /**
37
41
  * Whether the button should be in the success state.
38
42
  */
@@ -45,5 +49,5 @@ export type Props = PropsWithSpread<{
45
49
  * [Button](?path=/docs/components-button--docs) in addition to those in the
46
50
  * props table:
47
51
  */
48
- declare const ActionButton: ({ appearance, children, className, disabled, inline, loading, success, ...buttonProps }: Props) => React.JSX.Element;
52
+ declare const ActionButton: ({ appearance, children, className, onClick, disabled, inline, loading, success, ...buttonProps }: Props) => React.JSX.Element;
49
53
  export default ActionButton;
@@ -1,4 +1,4 @@
1
- var _excluded = ["appearance", "children", "className", "disabled", "inline", "loading", "success"];
1
+ var _excluded = ["appearance", "children", "className", "onClick", "disabled", "inline", "loading", "success"];
2
2
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
3
3
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
4
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
@@ -25,6 +25,7 @@ var ActionButton = _ref => {
25
25
  appearance,
26
26
  children,
27
27
  className,
28
+ onClick,
28
29
  disabled = null,
29
30
  inline = false,
30
31
  loading = false,
@@ -103,8 +104,10 @@ var ActionButton = _ref => {
103
104
  "is-inline": inline
104
105
  });
105
106
  var showIcon = showLoader || showSuccess;
107
+ var isDisabled = disabled === null ? showLoader : disabled;
106
108
  var icon = showLoader && "spinner" || showSuccess && "success" || null;
107
109
  var iconLight = appearance === "positive" || appearance === "negative";
110
+ var onClickDisabled = e => e.preventDefault();
108
111
 
109
112
  // This component uses the base button element instead of the Button component
110
113
  // as the button requires a ref and Button would have to be updated to use
@@ -112,8 +115,9 @@ var ActionButton = _ref => {
112
115
  // typescript generics.
113
116
  return /*#__PURE__*/React.createElement("button", _extends({
114
117
  className: buttonClasses,
115
- disabled: disabled === null ? showLoader : disabled,
116
118
  ref: ref,
119
+ onClick: isDisabled ? onClickDisabled : onClick,
120
+ "aria-disabled": isDisabled || undefined,
117
121
  style: height && width ? {
118
122
  height: "".concat(height, "px"),
119
123
  width: "".concat(width, "px")
@@ -48,6 +48,10 @@ export type Props<D extends Record<string, unknown>> = PropsWithSpread<{
48
48
  * Whether the sort by needs to be reset after each data change.
49
49
  */
50
50
  autoResetSortBy?: boolean;
51
+ /**
52
+ * This will render between the header and the content.
53
+ */
54
+ subhead?: ReactNode;
51
55
  }, HTMLProps<HTMLTableElement>>;
52
56
  /**
53
57
  This is a [React](https://reactjs.org/) component to support many table use cases.
@@ -101,5 +105,5 @@ columns = {
101
105
  };
102
106
  ```
103
107
  */
104
- declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, autoResetSortBy, ...props }: Props<D>): React.JSX.Element;
108
+ declare function ModularTable<D extends Record<string, unknown>>({ data, columns, emptyMsg, footer, sortable, getHeaderProps, getRowProps, getCellProps, getRowId, initialSortColumn, initialSortDirection, autoResetSortBy, subhead, ...props }: Props<D>): React.JSX.Element;
105
109
  export default ModularTable;
@@ -1,4 +1,4 @@
1
- var _excluded = ["data", "columns", "emptyMsg", "footer", "sortable", "getHeaderProps", "getRowProps", "getCellProps", "getRowId", "initialSortColumn", "initialSortDirection", "autoResetSortBy"];
1
+ var _excluded = ["data", "columns", "emptyMsg", "footer", "sortable", "getHeaderProps", "getRowProps", "getCellProps", "getRowId", "initialSortColumn", "initialSortDirection", "autoResetSortBy", "subhead"];
2
2
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
3
3
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
4
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
@@ -107,7 +107,8 @@ function ModularTable(_ref) {
107
107
  getRowId,
108
108
  initialSortColumn,
109
109
  initialSortDirection,
110
- autoResetSortBy = false
110
+ autoResetSortBy = false,
111
+ subhead
111
112
  } = _ref,
112
113
  props = _objectWithoutProperties(_ref, _excluded);
113
114
  var sortBy = useMemo(() => initialSortColumn ? [{
@@ -157,7 +158,7 @@ function ModularTable(_ref) {
157
158
  // Only call this if we want it to be sortable too.
158
159
  sortable && isColumnSortable(column) ? column.getSortByToggleProps({
159
160
  title: undefined
160
- }) : {}])), column.render("Header")))))), /*#__PURE__*/React.createElement("tbody", getTableBodyProps(), generateRows(rows, prepareRow, getRowProps, getCellProps), showEmpty && /*#__PURE__*/React.createElement(TableRow, null, /*#__PURE__*/React.createElement(TableCell, {
161
+ }) : {}])), column.render("Header"))))), subhead), /*#__PURE__*/React.createElement("tbody", getTableBodyProps(), generateRows(rows, prepareRow, getRowProps, getCellProps), showEmpty && /*#__PURE__*/React.createElement(TableRow, null, /*#__PURE__*/React.createElement(TableCell, {
161
162
  colSpan: columns.length
162
163
  }, emptyMsg)), footer && /*#__PURE__*/React.createElement(TableRow, null, /*#__PURE__*/React.createElement(TableCell, {
163
164
  colSpan: columns.length
@@ -12,6 +12,7 @@ at the start of the group. In the following example sorting the columns will
12
12
  sort the group rows, then sort the sub-rows, but the group header always comes first.
13
13
  */
14
14
  export declare const Subrows: Story;
15
+ export declare const Subheading: Story;
15
16
  /**
16
17
  Example below shows a basic `ModularTable` with `SummaryButton` component in the footer.
17
18
  ```
@@ -338,6 +338,117 @@ export var Subrows = {
338
338
  }),
339
339
  name: "Subrows"
340
340
  };
341
+ export var Subheading = {
342
+ render: () => /*#__PURE__*/React.createElement(ModularTable, {
343
+ getCellProps: _ref9 => {
344
+ var {
345
+ value
346
+ } = _ref9;
347
+ return {
348
+ className: value === "1 minute" ? "p-heading--5" : ""
349
+ };
350
+ }
351
+ // eslint-disable-next-line react-hooks/rules-of-hooks
352
+ ,
353
+ columns: React.useMemo(() => [{
354
+ Header: "ID",
355
+ accessor: "buildId",
356
+ Cell: function (_Cell7) {
357
+ function Cell(_x7) {
358
+ return _Cell7.apply(this, arguments);
359
+ }
360
+ Cell.toString = function () {
361
+ return _Cell7.toString();
362
+ };
363
+ return Cell;
364
+ }(_ref10 => {
365
+ var {
366
+ value
367
+ } = _ref10;
368
+ return /*#__PURE__*/React.createElement("a", {
369
+ href: "#test"
370
+ }, "#", value);
371
+ })
372
+ }, {
373
+ Header: "Architecture",
374
+ accessor: "arch"
375
+ }, {
376
+ Header: "Build Duration",
377
+ accessor: "duration",
378
+ className: "u-hide--small"
379
+ }, {
380
+ Header: "Result",
381
+ accessor: "result",
382
+ Cell: function (_Cell8) {
383
+ function Cell(_x8) {
384
+ return _Cell8.apply(this, arguments);
385
+ }
386
+ Cell.toString = function () {
387
+ return _Cell8.toString();
388
+ };
389
+ return Cell;
390
+ }(_ref11 => {
391
+ var {
392
+ value
393
+ } = _ref11;
394
+ switch (value) {
395
+ case "released":
396
+ return "Released";
397
+ case "failed":
398
+ return "Failed";
399
+ default:
400
+ return "Unknown";
401
+ }
402
+ }),
403
+ getCellIcon: _ref12 => {
404
+ var {
405
+ value
406
+ } = _ref12;
407
+ switch (value) {
408
+ case "released":
409
+ return ICONS.success;
410
+ case "failed":
411
+ return ICONS.error;
412
+ default:
413
+ return false;
414
+ }
415
+ }
416
+ }, {
417
+ Header: "Build Finished",
418
+ accessor: "finished",
419
+ className: "u-align-text--right"
420
+ }], [])
421
+ // eslint-disable-next-line react-hooks/rules-of-hooks
422
+ ,
423
+ data: React.useMemo(() => [{
424
+ buildId: "5432",
425
+ arch: "arm64",
426
+ duration: "5 minutes",
427
+ result: "released",
428
+ finished: "10 minutes ago"
429
+ }, {
430
+ buildId: "1234",
431
+ arch: "armhf",
432
+ duration: "5 minutes",
433
+ result: "failed",
434
+ finished: "over 1 year ago"
435
+ }, {
436
+ buildId: "1111",
437
+ arch: "test64",
438
+ duration: "1 minute",
439
+ result: "other",
440
+ finished: "ages ago"
441
+ }], []),
442
+ subhead: /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", {
443
+ colSpan: 5,
444
+ className: "p-text--default",
445
+ style: {
446
+ textTransform: "none"
447
+ }
448
+ }, "Showing 3 of 3 results"))
449
+ }),
450
+ name: "Subheading"
451
+ };
341
452
 
342
453
  /**
343
454
  Example below shows a basic `ModularTable` with `SummaryButton` component in the footer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonical/react-components",
3
- "version": "3.8.2",
3
+ "version": "3.9.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "author": {
@@ -81,7 +81,7 @@
81
81
  "sass": "1.85.0",
82
82
  "sass-loader": "16.0.5",
83
83
  "semantic-release": "25.0.2",
84
- "storybook": "8.5.6",
84
+ "storybook": "8.6.15",
85
85
  "strip-ansi": "7.1.0",
86
86
  "style-loader": "4.0.0",
87
87
  "stylelint": "16.14.1",
@@ -93,7 +93,7 @@
93
93
  "tsc-alias": "1.8.10",
94
94
  "typescript": "5.7.3",
95
95
  "typescript-eslint": "8.24.1",
96
- "vanilla-framework": "4.38.0",
96
+ "vanilla-framework": "4.39.0",
97
97
  "wait-on": "8.0.2",
98
98
  "webpack": "5.98.0"
99
99
  },