@canonical/react-components 3.9.1 → 3.11.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 (47) hide show
  1. package/dist/components/ConfirmationButton/ConfirmationButton.js +5 -5
  2. package/dist/components/ConfirmationModal/ConfirmationModal.d.ts +5 -1
  3. package/dist/components/ConfirmationModal/ConfirmationModal.js +9 -3
  4. package/dist/components/PrefixedInput/PrefixedInput.d.ts +13 -0
  5. package/dist/components/PrefixedInput/PrefixedInput.js +64 -0
  6. package/dist/components/PrefixedInput/PrefixedInput.scss +22 -0
  7. package/dist/components/PrefixedInput/PrefixedInput.stories.d.ts +11 -0
  8. package/dist/components/PrefixedInput/PrefixedInput.stories.js +58 -0
  9. package/dist/components/PrefixedInput/PrefixedInput.test.d.ts +1 -0
  10. package/dist/components/PrefixedInput/index.d.ts +1 -0
  11. package/dist/components/PrefixedInput/index.js +13 -0
  12. package/dist/components/PrefixedIpInput/PrefixedIpInput.d.ts +27 -0
  13. package/dist/components/PrefixedIpInput/PrefixedIpInput.js +65 -0
  14. package/dist/components/PrefixedIpInput/PrefixedIpInput.stories.d.ts +13 -0
  15. package/dist/components/PrefixedIpInput/PrefixedIpInput.stories.js +137 -0
  16. package/dist/components/PrefixedIpInput/PrefixedIpInput.test.d.ts +1 -0
  17. package/dist/components/PrefixedIpInput/index.d.ts +2 -0
  18. package/dist/components/PrefixedIpInput/index.js +56 -0
  19. package/dist/components/PrefixedIpInput/utils.d.ts +39 -0
  20. package/dist/components/PrefixedIpInput/utils.js +125 -0
  21. package/dist/components/PrefixedIpInput/utils.test.d.ts +1 -0
  22. package/dist/esm/components/ConfirmationButton/ConfirmationButton.js +5 -5
  23. package/dist/esm/components/ConfirmationModal/ConfirmationModal.d.ts +5 -1
  24. package/dist/esm/components/ConfirmationModal/ConfirmationModal.js +9 -3
  25. package/dist/esm/components/PrefixedInput/PrefixedInput.d.ts +13 -0
  26. package/dist/esm/components/PrefixedInput/PrefixedInput.js +57 -0
  27. package/dist/esm/components/PrefixedInput/PrefixedInput.scss +22 -0
  28. package/dist/esm/components/PrefixedInput/PrefixedInput.stories.d.ts +11 -0
  29. package/dist/esm/components/PrefixedInput/PrefixedInput.stories.js +51 -0
  30. package/dist/esm/components/PrefixedInput/PrefixedInput.test.d.ts +1 -0
  31. package/dist/esm/components/PrefixedInput/index.d.ts +1 -0
  32. package/dist/esm/components/PrefixedInput/index.js +1 -0
  33. package/dist/esm/components/PrefixedIpInput/PrefixedIpInput.d.ts +27 -0
  34. package/dist/esm/components/PrefixedIpInput/PrefixedIpInput.js +58 -0
  35. package/dist/esm/components/PrefixedIpInput/PrefixedIpInput.stories.d.ts +13 -0
  36. package/dist/esm/components/PrefixedIpInput/PrefixedIpInput.stories.js +128 -0
  37. package/dist/esm/components/PrefixedIpInput/PrefixedIpInput.test.d.ts +1 -0
  38. package/dist/esm/components/PrefixedIpInput/index.d.ts +2 -0
  39. package/dist/esm/components/PrefixedIpInput/index.js +2 -0
  40. package/dist/esm/components/PrefixedIpInput/utils.d.ts +39 -0
  41. package/dist/esm/components/PrefixedIpInput/utils.js +112 -0
  42. package/dist/esm/components/PrefixedIpInput/utils.test.d.ts +1 -0
  43. package/dist/esm/index.d.ts +4 -0
  44. package/dist/esm/index.js +2 -0
  45. package/dist/index.d.ts +4 -0
  46. package/dist/index.js +65 -0
  47. package/package.json +1 -1
@@ -37,8 +37,7 @@ const ConfirmationButton = _ref => {
37
37
  const {
38
38
  openPortal,
39
39
  closePortal,
40
- isOpen,
41
- Portal
40
+ isOpen
42
41
  } = (0, _external.usePortal)();
43
42
  const handleCancelModal = () => {
44
43
  closePortal();
@@ -64,13 +63,14 @@ const ConfirmationButton = _ref => {
64
63
  }
65
64
  shiftClickEnabled ? handleShiftClick(e) : openPortal(e);
66
65
  };
67
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isOpen && /*#__PURE__*/_react.default.createElement(Portal, null, /*#__PURE__*/_react.default.createElement(_ConfirmationModal.default, _extends({}, confirmationModalProps, {
66
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isOpen && /*#__PURE__*/_react.default.createElement(_ConfirmationModal.default, _extends({}, confirmationModalProps, {
68
67
  close: handleCancelModal,
69
68
  confirmButtonLabel: confirmationModalProps.confirmButtonLabel,
70
- onConfirm: handleConfirmModal
69
+ onConfirm: handleConfirmModal,
70
+ renderInPortal: true
71
71
  }), confirmationModalProps.children, showShiftClickHint && /*#__PURE__*/_react.default.createElement("p", {
72
72
  className: "p-text--small u-text--muted u-hide--small"
73
- }, "Next time, you can skip this confirmation by holding", " ", /*#__PURE__*/_react.default.createElement("code", null, "SHIFT"), " and clicking the action."))), /*#__PURE__*/_react.default.createElement(_ActionButton.default, _extends({}, actionButtonProps, {
73
+ }, "Next time, you can skip this confirmation by holding", " ", /*#__PURE__*/_react.default.createElement("code", null, "SHIFT"), " and clicking the action.")), /*#__PURE__*/_react.default.createElement(_ActionButton.default, _extends({}, actionButtonProps, {
74
74
  onClick: handleClick,
75
75
  title: generateTitle(onHoverText !== null && onHoverText !== void 0 ? onHoverText : confirmationModalProps.confirmButtonLabel)
76
76
  }), actionButtonProps.children));
@@ -45,9 +45,13 @@ export type Props = PropsWithSpread<{
45
45
  * Whether the confirm button should be disabled.
46
46
  */
47
47
  confirmButtonDisabled?: boolean;
48
+ /**
49
+ * Whether to render the modal inside a Portal component.
50
+ */
51
+ renderInPortal?: boolean;
48
52
  }, Omit<ModalProps, "buttonRow">>;
49
53
  /**
50
54
  * `ConfirmationModal` is a specialised version of the [Modal](?path=/docs/modal--default-story) component to prompt a confirmation from the user before executing an action.
51
55
  */
52
- export declare const ConfirmationModal: ({ cancelButtonLabel, cancelButtonProps, children, confirmButtonAppearance, confirmButtonLabel, confirmExtra, onConfirm, confirmButtonLoading, confirmButtonDisabled, confirmButtonProps, ...props }: Props) => React.JSX.Element;
56
+ export declare const ConfirmationModal: ({ cancelButtonLabel, cancelButtonProps, children, confirmButtonAppearance, confirmButtonLabel, confirmExtra, onConfirm, confirmButtonLoading, confirmButtonDisabled, confirmButtonProps, renderInPortal, ...props }: Props) => React.JSX.Element;
53
57
  export default ConfirmationModal;
@@ -8,7 +8,8 @@ var _react = _interopRequireDefault(require("react"));
8
8
  var _Button = _interopRequireDefault(require("../Button"));
9
9
  var _Modal = _interopRequireDefault(require("../Modal"));
10
10
  var _ActionButton = _interopRequireDefault(require("../ActionButton"));
11
- const _excluded = ["cancelButtonLabel", "cancelButtonProps", "children", "confirmButtonAppearance", "confirmButtonLabel", "confirmExtra", "onConfirm", "confirmButtonLoading", "confirmButtonDisabled", "confirmButtonProps"];
11
+ var _external = require("../../external");
12
+ const _excluded = ["cancelButtonLabel", "cancelButtonProps", "children", "confirmButtonAppearance", "confirmButtonLabel", "confirmExtra", "onConfirm", "confirmButtonLoading", "confirmButtonDisabled", "confirmButtonProps", "renderInPortal"];
12
13
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
14
  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); }
14
15
  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; }
@@ -28,9 +29,13 @@ const ConfirmationModal = _ref => {
28
29
  onConfirm,
29
30
  confirmButtonLoading,
30
31
  confirmButtonDisabled,
31
- confirmButtonProps
32
+ confirmButtonProps,
33
+ renderInPortal = false
32
34
  } = _ref,
33
35
  props = _objectWithoutProperties(_ref, _excluded);
36
+ const {
37
+ Portal
38
+ } = (0, _external.usePortal)();
34
39
  const handleClick = action => event => {
35
40
  if (!props.shouldPropagateClickEvent) {
36
41
  event.stopPropagation();
@@ -39,7 +44,7 @@ const ConfirmationModal = _ref => {
39
44
  action(event);
40
45
  }
41
46
  };
42
- return /*#__PURE__*/_react.default.createElement(_Modal.default, _extends({
47
+ const ModalElement = /*#__PURE__*/_react.default.createElement(_Modal.default, _extends({
43
48
  buttonRow: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, confirmExtra, /*#__PURE__*/_react.default.createElement(_Button.default, _extends({}, cancelButtonProps, {
44
49
  type: (_cancelButtonProps$ty = cancelButtonProps === null || cancelButtonProps === void 0 ? void 0 : cancelButtonProps.type) !== null && _cancelButtonProps$ty !== void 0 ? _cancelButtonProps$ty : "button",
45
50
  className: "u-no-margin--bottom",
@@ -52,6 +57,7 @@ const ConfirmationModal = _ref => {
52
57
  disabled: confirmButtonDisabled
53
58
  }), confirmButtonLabel))
54
59
  }, props), children);
60
+ return renderInPortal ? /*#__PURE__*/_react.default.createElement(Portal, null, ModalElement) : ModalElement;
55
61
  };
56
62
  exports.ConfirmationModal = ConfirmationModal;
57
63
  var _default = exports.default = ConfirmationModal;
@@ -0,0 +1,13 @@
1
+ import { type ReactElement } from "react";
2
+ import { type InputProps } from "../Input";
3
+ import "./PrefixedInput.scss";
4
+ import { PropsWithSpread } from "../../types";
5
+ export type PrefixedInputProps = PropsWithSpread<{
6
+ /**
7
+ * The immutable text that appears at the beginning of the input field.
8
+ * This text is not editable by the user and visually appears inside the input.
9
+ */
10
+ immutableText: string;
11
+ }, Omit<InputProps, "type">>;
12
+ declare const PrefixedInput: ({ immutableText, ...props }: PrefixedInputProps) => ReactElement;
13
+ export default PrefixedInput;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _Input = _interopRequireDefault(require("../Input"));
9
+ var _classnames = _interopRequireDefault(require("classnames"));
10
+ require("./PrefixedInput.scss");
11
+ var _useListener = require("../../hooks/useListener");
12
+ const _excluded = ["immutableText"];
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
15
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
16
+ 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); }
17
+ 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; }
18
+ 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; }
19
+ // export type PrefixedInputProps = Omit<InputProps, "type"> & {
20
+ // /**
21
+ // * The immutable text that appears at the beginning of the input field.
22
+ // * This text is not editable by the user and visually appears inside the input.
23
+ // */
24
+ // immutableText: string;
25
+ // };
26
+
27
+ const PrefixedInput = _ref => {
28
+ let {
29
+ immutableText
30
+ } = _ref,
31
+ props = _objectWithoutProperties(_ref, _excluded);
32
+ const prefixTextRef = (0, _react.useRef)(null);
33
+ const inputWrapperRef = (0, _react.useRef)(null);
34
+ const updatePadding = (0, _react.useCallback)(() => {
35
+ var _inputWrapperRef$curr;
36
+ const prefixElement = prefixTextRef.current;
37
+ const inputElement = (_inputWrapperRef$curr = inputWrapperRef.current) === null || _inputWrapperRef$curr === void 0 ? void 0 : _inputWrapperRef$curr.querySelector("input");
38
+ if (prefixElement && inputElement) {
39
+ // Adjust the left padding of the input to be the same width as the immutable text.
40
+ // This displays the user input and the unchangeable text together as one combined string.
41
+ const prefixWidth = prefixElement.getBoundingClientRect().width;
42
+ inputElement.style.paddingLeft = "".concat(prefixWidth, "px");
43
+ }
44
+ }, []);
45
+ (0, _useListener.useListener)(window, updatePadding, "resize", true);
46
+ (0, _react.useLayoutEffect)(() => {
47
+ updatePadding();
48
+ }, [immutableText, props.label, updatePadding]);
49
+ return /*#__PURE__*/_react.default.createElement("div", {
50
+ className: (0, _classnames.default)("prefixed-input", {
51
+ "prefixed-input--with-label": !!props.label
52
+ })
53
+ }, /*#__PURE__*/_react.default.createElement("div", {
54
+ className: "prefixed-input__text",
55
+ ref: prefixTextRef
56
+ }, immutableText), /*#__PURE__*/_react.default.createElement("div", {
57
+ ref: inputWrapperRef
58
+ }, /*#__PURE__*/_react.default.createElement(_Input.default, _extends({}, props, {
59
+ className: (0, _classnames.default)("prefixed-input__input", props.className),
60
+ type: "text",
61
+ wrapperClassName: (0, _classnames.default)("prefixed-input__wrapper", props.wrapperClassName)
62
+ }))));
63
+ };
64
+ var _default = exports.default = PrefixedInput;
@@ -0,0 +1,22 @@
1
+ @import "vanilla-framework";
2
+
3
+ .prefixed-input {
4
+ position: relative;
5
+
6
+ .prefixed-input__input {
7
+ padding-top: 0.25rem;
8
+ }
9
+
10
+ .prefixed-input__text {
11
+ padding-left: $spv--large;
12
+ padding-top: 0.3rem;
13
+ pointer-events: none;
14
+ position: absolute;
15
+ }
16
+
17
+ &--with-label {
18
+ .prefixed-input__text {
19
+ top: 2.5rem;
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,11 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import PrefixedInput from "./PrefixedInput";
3
+ declare const meta: Meta<typeof PrefixedInput>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PrefixedInput>;
6
+ export declare const Default: Story;
7
+ export declare const WithLabel: Story;
8
+ export declare const Disabled: Story;
9
+ export declare const WithError: Story;
10
+ export declare const WithHelpText: Story;
11
+ export declare const Required: Story;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.WithLabel = exports.WithHelpText = exports.WithError = exports.Required = exports.Disabled = exports.Default = void 0;
7
+ var _PrefixedInput = _interopRequireDefault(require("./PrefixedInput"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ const meta = {
10
+ component: _PrefixedInput.default,
11
+ tags: ["autodocs"]
12
+ };
13
+ var _default = exports.default = meta;
14
+ const Default = exports.Default = {
15
+ args: {
16
+ immutableText: "https://",
17
+ placeholder: "example.com"
18
+ }
19
+ };
20
+ const WithLabel = exports.WithLabel = {
21
+ args: {
22
+ immutableText: "https://",
23
+ label: "Website URL",
24
+ placeholder: "example.com"
25
+ }
26
+ };
27
+ const Disabled = exports.Disabled = {
28
+ args: {
29
+ immutableText: "@",
30
+ label: "Username",
31
+ placeholder: "username",
32
+ disabled: true
33
+ }
34
+ };
35
+ const WithError = exports.WithError = {
36
+ args: {
37
+ immutableText: "https://",
38
+ label: "Website URL",
39
+ placeholder: "example.com",
40
+ error: "Invalid URL format"
41
+ }
42
+ };
43
+ const WithHelpText = exports.WithHelpText = {
44
+ args: {
45
+ immutableText: "User ID:",
46
+ label: "User Identifier",
47
+ placeholder: " Enter user ID",
48
+ help: "This will be used to identify your account"
49
+ }
50
+ };
51
+ const Required = exports.Required = {
52
+ args: {
53
+ immutableText: "https://",
54
+ label: "Website URL",
55
+ placeholder: "example.com",
56
+ required: true
57
+ }
58
+ };
@@ -0,0 +1 @@
1
+ export { default, type PrefixedInputProps } from "./PrefixedInput";
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _PrefixedInput.default;
10
+ }
11
+ });
12
+ var _PrefixedInput = _interopRequireDefault(require("./PrefixedInput"));
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -0,0 +1,27 @@
1
+ import { type ReactElement } from "react";
2
+ import { type PrefixedInputProps } from "../PrefixedInput";
3
+ import { PropsWithSpread } from "../../types";
4
+ export type PrefixedIpInputProps = PropsWithSpread<{
5
+ /**
6
+ * The CIDR for the subnet (e.g., "192.168.1.0/24" or "2001:db8::/32").
7
+ * Used to calculate the immutable prefix and available IP range.
8
+ */
9
+ cidr: string;
10
+ /**
11
+ * The full IP address value (if available).
12
+ * For IPv4: e.g., "192.168.1.100"
13
+ * For IPv6: e.g., "2001:db8::1"
14
+ */
15
+ ip: string;
16
+ /**
17
+ * The name attribute for the input field.
18
+ */
19
+ name: string;
20
+ /**
21
+ * Callback function that is called when the IP address changes.
22
+ * Receives the full IP address as a string parameter.
23
+ */
24
+ onIpChange: (ip: string) => void;
25
+ }, Omit<PrefixedInputProps, "immutableText" | "maxLength" | "placeholder" | "name">>;
26
+ declare const PrefixedIpInput: ({ cidr, help, onIpChange, ip, name, ...props }: PrefixedIpInputProps) => ReactElement;
27
+ export default PrefixedIpInput;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _PrefixedInput = _interopRequireDefault(require("../PrefixedInput"));
9
+ var _utils = require("./utils");
10
+ const _excluded = ["cidr", "help", "onIpChange", "ip", "name"];
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ 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); }
13
+ 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; }
14
+ 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; }
15
+ const PrefixedIpInput = _ref => {
16
+ let {
17
+ cidr,
18
+ help,
19
+ onIpChange,
20
+ ip,
21
+ name
22
+ } = _ref,
23
+ props = _objectWithoutProperties(_ref, _excluded);
24
+ const [networkAddress] = cidr.split("/");
25
+ const isIPV4 = (0, _utils.isIPv4)(networkAddress);
26
+ const [immutable, editable] = (0, _utils.getImmutableAndEditable)(cidr);
27
+ const inputValue = isIPV4 ? ip.split(".").slice(immutable.split(".").length).join(".") : ip.replace(immutable, "");
28
+ const getIPv4MaxLength = () => {
29
+ const immutableOctetsLength = immutable.split(".").length;
30
+ const lengths = [15, 11, 7, 3]; // Corresponding to 0-3 immutable octets
31
+ return lengths[immutableOctetsLength];
32
+ };
33
+ const maxLength = isIPV4 ? getIPv4MaxLength() : editable.length;
34
+ const placeholder = props.disabled ? "" : editable;
35
+ const setIp = editableValue => {
36
+ const fullIp = editableValue ? isIPV4 ? "".concat(immutable, ".").concat(editableValue) : "".concat(immutable).concat(editableValue) : "";
37
+ onIpChange(fullIp);
38
+ };
39
+ const handlePaste = e => {
40
+ e.preventDefault();
41
+ const pastedText = e.clipboardData.getData("text");
42
+ if (isIPV4) {
43
+ const octets = pastedText.split(".");
44
+ const trimmed = octets.slice(0 - editable.split(".").length);
45
+ const ip = trimmed.join(".");
46
+ setIp(ip);
47
+ } else {
48
+ const ip = pastedText.replace(immutable, "");
49
+ setIp(ip);
50
+ }
51
+ };
52
+ return /*#__PURE__*/_react.default.createElement(_PrefixedInput.default, _extends({
53
+ help: help ? help : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, " ", isIPV4 ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, " ", "The available range in this subnet is", " ", /*#__PURE__*/_react.default.createElement("code", null, immutable, ".", editable, " ")) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, " ", "The available IPV6 address range is", " ", /*#__PURE__*/_react.default.createElement("code", null, immutable, editable, " ")), "."),
54
+ immutableText: isIPV4 ? "".concat(immutable, ".") : immutable,
55
+ maxLength: maxLength,
56
+ name: name,
57
+ onPaste: handlePaste,
58
+ value: inputValue,
59
+ onChange: e => {
60
+ setIp(e.target.value);
61
+ },
62
+ placeholder: placeholder
63
+ }, props));
64
+ };
65
+ var _default = exports.default = PrefixedIpInput;
@@ -0,0 +1,13 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import PrefixedIpInput from "./PrefixedIpInput";
3
+ declare const meta: Meta<typeof PrefixedIpInput>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof PrefixedIpInput>;
6
+ export declare const IPv4Default: Story;
7
+ export declare const IPv4WithValue: Story;
8
+ export declare const IPv4WithError: Story;
9
+ export declare const IPv4Disabled: Story;
10
+ export declare const IPv6Default: Story;
11
+ export declare const IPv6WithValue: Story;
12
+ export declare const WithCustomHelp: Story;
13
+ export declare const Required: Story;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.WithCustomHelp = exports.Required = exports.IPv6WithValue = exports.IPv6Default = exports.IPv4WithValue = exports.IPv4WithError = exports.IPv4Disabled = exports.IPv4Default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _PrefixedIpInput = _interopRequireDefault(require("./PrefixedIpInput"));
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
12
+ 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); }
13
+ const PrefixedIpInputWrapper = args => {
14
+ const [ip, setIp] = (0, _react.useState)(args.ip);
15
+ return /*#__PURE__*/_react.default.createElement(_PrefixedIpInput.default, _extends({}, args, {
16
+ ip: ip,
17
+ onIpChange: newIp => {
18
+ var _args$onIpChange;
19
+ setIp(newIp);
20
+ (_args$onIpChange = args.onIpChange) === null || _args$onIpChange === void 0 || _args$onIpChange.call(args, newIp);
21
+ }
22
+ }));
23
+ };
24
+ const meta = {
25
+ component: _PrefixedIpInput.default,
26
+ tags: ["autodocs"],
27
+ argTypes: {
28
+ ip: {
29
+ control: "text"
30
+ },
31
+ cidr: {
32
+ control: "text"
33
+ },
34
+ label: {
35
+ control: "text"
36
+ },
37
+ name: {
38
+ control: "text"
39
+ },
40
+ error: {
41
+ control: "text"
42
+ },
43
+ help: {
44
+ control: "text"
45
+ },
46
+ disabled: {
47
+ control: "boolean"
48
+ },
49
+ required: {
50
+ control: "boolean"
51
+ }
52
+ },
53
+ render: args => /*#__PURE__*/_react.default.createElement(PrefixedIpInputWrapper, args)
54
+ };
55
+ var _default = exports.default = meta;
56
+ const IPv4Default = exports.IPv4Default = {
57
+ name: "IPv4 default",
58
+ args: {
59
+ cidr: "192.168.1.0/24",
60
+ ip: "",
61
+ name: "ip-address",
62
+ label: "IP Address",
63
+ onIpChange: ip => console.log("IP changed:", ip)
64
+ }
65
+ };
66
+ const IPv4WithValue = exports.IPv4WithValue = {
67
+ name: "IPv4 with value",
68
+ args: {
69
+ cidr: "192.168.1.0/24",
70
+ ip: "192.168.1.100",
71
+ name: "ip-address",
72
+ label: "IP Address",
73
+ onIpChange: ip => console.log("IP changed:", ip)
74
+ }
75
+ };
76
+ const IPv4WithError = exports.IPv4WithError = {
77
+ name: "IPv4 with error",
78
+ args: {
79
+ cidr: "192.168.1.0/24",
80
+ ip: "192.168.1.256",
81
+ name: "ip-address",
82
+ label: "IP Address",
83
+ error: "Invalid IP address",
84
+ onIpChange: ip => console.log("IP changed:", ip)
85
+ }
86
+ };
87
+ const IPv4Disabled = exports.IPv4Disabled = {
88
+ name: "IPv4 disabled",
89
+ args: {
90
+ cidr: "192.168.1.0/24",
91
+ ip: "192.168.1.50",
92
+ name: "ip-address",
93
+ label: "IP Address",
94
+ disabled: true,
95
+ onIpChange: ip => console.log("IP changed:", ip)
96
+ }
97
+ };
98
+ const IPv6Default = exports.IPv6Default = {
99
+ name: "IPv6 default",
100
+ args: {
101
+ cidr: "2001:db8::/32",
102
+ ip: "",
103
+ name: "ipv6-address",
104
+ label: "IPv6 Address",
105
+ onIpChange: ip => console.log("IP changed:", ip)
106
+ }
107
+ };
108
+ const IPv6WithValue = exports.IPv6WithValue = {
109
+ name: "IPv6 with value",
110
+ args: {
111
+ cidr: "2001:db8::/32",
112
+ ip: "2001:db8::1",
113
+ name: "ipv6-address",
114
+ label: "IPv6 Address",
115
+ onIpChange: ip => console.log("IP changed:", ip)
116
+ }
117
+ };
118
+ const WithCustomHelp = exports.WithCustomHelp = {
119
+ args: {
120
+ cidr: "10.0.0.0/16",
121
+ ip: "",
122
+ name: "ip-address",
123
+ label: "IP Address",
124
+ help: "Enter a custom IP address for this device",
125
+ onIpChange: ip => console.log("IP changed:", ip)
126
+ }
127
+ };
128
+ const Required = exports.Required = {
129
+ args: {
130
+ cidr: "192.168.0.0/24",
131
+ ip: "",
132
+ name: "ip-address",
133
+ label: "IP Address",
134
+ required: true,
135
+ onIpChange: ip => console.log("IP changed:", ip)
136
+ }
137
+ };
@@ -0,0 +1,2 @@
1
+ export { default, type PrefixedIpInputProps } from "./PrefixedIpInput";
2
+ export { isIPv4, getIpRangeFromCidr, getFirstValidIp, convertIpToUint32, isIpInSubnet, getImmutableAndEditableOctets, getImmutableAndEditable, } from "./utils";
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "convertIpToUint32", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _utils.convertIpToUint32;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "default", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _PrefixedIpInput.default;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "getFirstValidIp", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _utils.getFirstValidIp;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "getImmutableAndEditable", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _utils.getImmutableAndEditable;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "getImmutableAndEditableOctets", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _utils.getImmutableAndEditableOctets;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "getIpRangeFromCidr", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _utils.getIpRangeFromCidr;
40
+ }
41
+ });
42
+ Object.defineProperty(exports, "isIPv4", {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _utils.isIPv4;
46
+ }
47
+ });
48
+ Object.defineProperty(exports, "isIpInSubnet", {
49
+ enumerable: true,
50
+ get: function () {
51
+ return _utils.isIpInSubnet;
52
+ }
53
+ });
54
+ var _PrefixedIpInput = _interopRequireDefault(require("./PrefixedIpInput"));
55
+ var _utils = require("./utils");
56
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Checks if a given IP address is a valid IPv4 address.
3
+ * @param ip The IP address to check
4
+ * @returns True if the IP is a valid IPv4 address, false otherwise
5
+ */
6
+ export declare const isIPv4: (ip: string) => boolean;
7
+ /**
8
+ * Takes a subnet CIDR notation (IPv4) and returns the first and last IP of the subnet.
9
+ * The network and host addresses are excluded.
10
+ *
11
+ * @param cidr The CIDR notation of the subnet
12
+ * @returns The first and last valid IP addresses as two strings in a list.
13
+ */
14
+ export declare const getIpRangeFromCidr: (cidr: string) => string[];
15
+ export declare const getFirstValidIp: (ip: string) => string;
16
+ export declare const convertIpToUint32: (ip: string) => number;
17
+ /**
18
+ * Checks if an IPv4 address is valid for the given subnet.
19
+ *
20
+ * @param ip The IPv4 address to check, as a string
21
+ * @param cidr The subnet's CIDR notation e.g. 192.168.0.0/24
22
+ * @returns True if the IP is in the subnet, false otherwise
23
+ */
24
+ export declare const isIpInSubnet: (ip: string, cidr: string) => boolean;
25
+ /**
26
+ * Separates the immutable and editable octets of an IPv4 subnet range.
27
+ *
28
+ * @param startIp The start IP of the subnet
29
+ * @param endIp The end IP of the subnet
30
+ * @returns The immutable and editable octects as two strings in a list
31
+ */
32
+ export declare const getImmutableAndEditableOctets: (startIp: string, endIp: string) => string[];
33
+ /**
34
+ * Get the immutable and editable parts of an IPv4 or IPv6 subnet.
35
+ *
36
+ * @param cidr The CIDR notation of the subnet
37
+ * @returns The immutable and editable as two strings in a list
38
+ */
39
+ export declare const getImmutableAndEditable: (cidr: string) => string[];