@carbon/utilities-react 0.20.0 → 0.21.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
@@ -19,6 +19,44 @@ instead:
19
19
  yarn add @carbon/utilities-react
20
20
  ```
21
21
 
22
+ ## Maintainer information
23
+
24
+ This package uses a convention-based multi-entry build. The supported public API
25
+ consists of two parts.
26
+
27
+ 1. The root entrypoint
28
+
29
+ ```js
30
+ import { utility } from '@carbon/utilities-react';
31
+ ```
32
+
33
+ 2. Any top-level module with a `src/<name>/index.*` file
34
+
35
+ ```js
36
+ import { utility } from '@carbon/utilities-react/utility';
37
+ ```
38
+
39
+ Review the
40
+ [architecture decision record (ADR)](../../docs/decisions/0004-adopt-explicit-package-entrypoints-for-utilities.md)
41
+ for more detail on how and why this approach is used.
42
+
43
+ ### Adding a utility
44
+
45
+ 1. Create a new top-level directory under `src/`
46
+ 2. Export the public API for that utility from `src/<name>/index.ts`,
47
+ `index.tsx`, `index.js`, or `index.jsx`
48
+ 3. Re-export it from `src/index.ts` if it should also be available from the
49
+ package root
50
+ 4. Build the package and verify the generated outputs under `es/<name>/index.*`
51
+ and `lib/<name>/index.js`
52
+
53
+ ```text
54
+ src/
55
+ someReactUtility/
56
+ index.tsx
57
+ someReactUtility.tsx
58
+ ```
59
+
22
60
  ## 🙌 Contributing
23
61
 
24
62
  We're always looking for contributors to help us fix bugs, build new features,
@@ -0,0 +1,2 @@
1
+ import { i as StepGroup, n as useStepContext, r as StepContextType, t as StepProvider } from "../chunk.js";
2
+ export { type StepContextType, StepGroup, StepProvider, useStepContext };
@@ -1 +1,3 @@
1
- import{StepGroup as p}from"./StepGroup";import{StepProvider as r,useStepContext as x}from"./StepContext";export{p as StepGroup,r as StepProvider,x as useStepContext};
1
+ import { n as useStepContext, r as StepGroup, t as StepProvider } from "../chunk.js";
2
+
3
+ export { StepGroup, StepProvider, useStepContext };
package/es/chunk.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import React, { Dispatch, ReactNode, SetStateAction } from "react";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
+
4
+ //#region src/StepFlow/StepGroup.d.ts
5
+ interface StepGroupProps {
6
+ children: React.ReactNode;
7
+ }
8
+ /**
9
+ * Container for steps. The children are filtered for only truthy values (via Children.toArray)
10
+ * and only the current step is returned from this component based on the `currentStep` value
11
+ * from `useStepContext`.
12
+ */
13
+ declare const StepGroup: ({
14
+ children
15
+ }: StepGroupProps) => string | number | bigint | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined>;
16
+ //#endregion
17
+ //#region src/StepFlow/types.d.ts
18
+ /**
19
+ * This interface should be extended by the consumer to match their own unique
20
+ * use case given the fields within their own stepped experience.
21
+ */
22
+ interface formStateType {
23
+ [key: string]: unknown;
24
+ }
25
+ interface StepContextType {
26
+ formState: formStateType;
27
+ setFormState: Dispatch<SetStateAction<formStateType>>;
28
+ totalSteps: number;
29
+ setTotalSteps: Dispatch<SetStateAction<number>>;
30
+ currentStep: number;
31
+ handleGoToStep: (step: number) => void;
32
+ handleNext: () => void;
33
+ handlePrevious: () => void;
34
+ }
35
+ //#endregion
36
+ //#region src/StepFlow/StepContext.d.ts
37
+ interface StepProviderProps {
38
+ children: ReactNode;
39
+ }
40
+ declare const StepProvider: ({
41
+ children
42
+ }: StepProviderProps) => react_jsx_runtime0.JSX.Element;
43
+ declare const useStepContext: () => StepContextType;
44
+ //#endregion
45
+ export { StepGroup as i, useStepContext as n, StepContextType as r, StepProvider as t };
package/es/chunk.js ADDED
@@ -0,0 +1,60 @@
1
+ import React, { createContext, useContext, useEffect, useState } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+
4
+ //#region src/StepFlow/StepGroup.tsx
5
+ /**
6
+ * Copyright IBM Corp. 2025, 2025
7
+ *
8
+ * This source code is licensed under the Apache-2.0 license found in the
9
+ * LICENSE file in the root directory of this source tree.
10
+ */
11
+ /**
12
+ * Container for steps. The children are filtered for only truthy values (via Children.toArray)
13
+ * and only the current step is returned from this component based on the `currentStep` value
14
+ * from `useStepContext`.
15
+ */
16
+ const StepGroup = ({ children }) => {
17
+ const { setTotalSteps, currentStep } = useStepContext();
18
+ const childrenArray = React.Children.toArray(children);
19
+ useEffect(() => {
20
+ setTotalSteps(childrenArray.length);
21
+ }, [childrenArray.length, setTotalSteps]);
22
+ return childrenArray[currentStep - 1];
23
+ };
24
+
25
+ //#endregion
26
+ //#region src/StepFlow/StepContext.tsx
27
+ /**
28
+ * Copyright IBM Corp. 2025, 2025
29
+ *
30
+ * This source code is licensed under the Apache-2.0 license found in the
31
+ * LICENSE file in the root directory of this source tree.
32
+ */
33
+ const StepContext = createContext(void 0);
34
+ const StepProvider = ({ children }) => {
35
+ const [totalSteps, setTotalSteps] = useState(1);
36
+ const [currentStep, setCurrentStep] = useState(1);
37
+ const [formState, setFormState] = useState({});
38
+ const context = {
39
+ formState,
40
+ setFormState,
41
+ totalSteps,
42
+ setTotalSteps,
43
+ currentStep,
44
+ handleGoToStep: (step) => setCurrentStep(step),
45
+ handleNext: () => setCurrentStep((step) => step + 1),
46
+ handlePrevious: () => setCurrentStep((step) => step - 1)
47
+ };
48
+ return /* @__PURE__ */ jsx(StepContext.Provider, {
49
+ value: context,
50
+ children
51
+ });
52
+ };
53
+ const useStepContext = () => {
54
+ const context = useContext(StepContext);
55
+ if (context === void 0) throw new Error("Context hook used outside of Step provider");
56
+ return context;
57
+ };
58
+
59
+ //#endregion
60
+ export { useStepContext as n, StepGroup as r, StepProvider as t };
package/es/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren } from "./useNoInteractiveChildren/index.js";
2
+ import { i as StepGroup, n as useStepContext, r as StepContextType, t as StepProvider } from "./chunk.js";
3
+ import "./StepFlow/index.js";
4
+ export * from "@carbon/utilities";
5
+ export { type StepContextType, StepGroup, StepProvider, getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren, useStepContext };
package/es/index.js CHANGED
@@ -1 +1,6 @@
1
- export*from"@carbon/utilities";export*from"./useNoInteractiveChildren";export*from"./StepFlow";
1
+ import { getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren } from "./useNoInteractiveChildren/index.js";
2
+ import { n as useStepContext, r as StepGroup, t as StepProvider } from "./chunk.js";
3
+
4
+ export * from "@carbon/utilities"
5
+
6
+ export { StepGroup, StepProvider, getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren, useStepContext };
@@ -0,0 +1,21 @@
1
+ //#region src/useNoInteractiveChildren/index.d.ts
2
+ declare function useNoInteractiveChildren(ref: any, message?: string): void;
3
+ declare function useInteractiveChildrenNeedDescription(ref: any, message?: string): void;
4
+ /**
5
+ * Determines if a given DOM node has interactive content, or is itself
6
+ * interactive. It returns the interactive node if one is found
7
+ *
8
+ * @param {HTMLElement} node
9
+ * @returns {HTMLElement}
10
+ */
11
+ declare function getInteractiveContent(node: HTMLElement): HTMLElement;
12
+ /**
13
+ * Determines if a given DOM node has a role, or has itself a role.
14
+ * It returns the node with a role if one is found
15
+ *
16
+ * @param {HTMLElement} node
17
+ * @returns {HTMLElement}
18
+ */
19
+ declare function getRoleContent(node: HTMLElement): HTMLElement;
20
+ //#endregion
21
+ export { getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren };
@@ -1,5 +1,80 @@
1
- import{useEffect as u}from"react";function f(r,e="component should have no interactive child nodes"){u(()=>{if(process.env.NODE_ENV==="production")return;const{current:t}=r,n=t?o(t):null;if(n){const i=`Error: ${e}.
1
+ import { useEffect } from "react";
2
2
 
3
- Instead found: ${n.outerHTML}`;throw console.error(i),new Error(i)}},[e,r])}function l(r,e="interactive child node(s) should have an `aria-describedby` property"){u(()=>{if(process.env.NODE_ENV==="production")return;const{current:t}=r,n=t?o(t):null;if(n&&!n.hasAttribute("aria-describedby"))throw new Error(`Error: ${e}.
3
+ //#region src/useNoInteractiveChildren/index.jsx
4
+ /**
5
+ * Copyright IBM Corp. 2016, 2026
6
+ *
7
+ * This source code is licensed under the Apache-2.0 license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ function useNoInteractiveChildren(ref, message = "component should have no interactive child nodes") {
11
+ useEffect(() => {
12
+ if (process.env.NODE_ENV === "production") return;
13
+ const { current } = ref;
14
+ const node = current ? getInteractiveContent(current) : null;
15
+ if (node) {
16
+ const errorMessage = `Error: ${message}.\n\nInstead found: ${node.outerHTML}`;
17
+ console.error(errorMessage);
18
+ throw new Error(errorMessage);
19
+ }
20
+ }, [message, ref]);
21
+ }
22
+ function useInteractiveChildrenNeedDescription(ref, message = `interactive child node(s) should have an \`aria-describedby\` property`) {
23
+ useEffect(() => {
24
+ if (process.env.NODE_ENV === "production") return;
25
+ const { current } = ref;
26
+ const node = current ? getInteractiveContent(current) : null;
27
+ if (node && !node.hasAttribute("aria-describedby")) throw new Error(`Error: ${message}.\n\nInstead found: ${node.outerHTML}`);
28
+ }, [message, ref]);
29
+ }
30
+ /**
31
+ * Determines if a given DOM node has interactive content, or is itself
32
+ * interactive. It returns the interactive node if one is found
33
+ *
34
+ * @param {HTMLElement} node
35
+ * @returns {HTMLElement}
36
+ */
37
+ function getInteractiveContent(node) {
38
+ if (!node || !node.childNodes) return null;
39
+ if (isFocusable(node)) return node;
40
+ for (const childNode of node.childNodes) {
41
+ const interactiveNode = getInteractiveContent(childNode);
42
+ if (interactiveNode) return interactiveNode;
43
+ }
44
+ return null;
45
+ }
46
+ /**
47
+ * Determines if a given DOM node has a role, or has itself a role.
48
+ * It returns the node with a role if one is found
49
+ *
50
+ * @param {HTMLElement} node
51
+ * @returns {HTMLElement}
52
+ */
53
+ function getRoleContent(node) {
54
+ if (!node || !node.childNodes) return null;
55
+ if (node?.getAttribute?.("role") && node.getAttribute("role") !== "") return node;
56
+ for (const childNode of node.childNodes) {
57
+ const roleNode = getRoleContent(childNode);
58
+ if (roleNode) return roleNode;
59
+ }
60
+ return null;
61
+ }
62
+ /**
63
+ * Determines if the given element is focusable, or not
64
+ *
65
+ * @param {HTMLElement} element
66
+ * @returns {boolean}
67
+ * @see https://github.com/w3c/aria-practices/blob/0553bb51588ffa517506e2a1b2ca1422ed438c5f/examples/js/utils.js#L68
68
+ */
69
+ function isFocusable(element) {
70
+ if (element.tabIndex === void 0 || element.tabIndex < 0) return false;
71
+ if (element.disabled) return false;
72
+ switch (element.nodeName) {
73
+ case "A": return !!element.href && element.rel !== "ignore";
74
+ case "INPUT": return element.type !== "hidden";
75
+ default: return true;
76
+ }
77
+ }
4
78
 
5
- Instead found: ${n.outerHTML}`)},[e,r])}function o(r){if(!r||!r.childNodes)return null;if(s(r))return r;for(const e of r.childNodes){const t=o(e);if(t)return t}return null}function c(r){if(!r||!r.childNodes)return null;if(r?.getAttribute?.("role")&&r.getAttribute("role")!=="")return r;for(const e of r.childNodes){const t=c(e);if(t)return t}return null}function s(r){if(r.tabIndex===void 0||r.tabIndex<0||r.disabled)return!1;switch(r.nodeName){case"A":return!!r.href&&r.rel!=="ignore";case"INPUT":return r.type!=="hidden";default:return!0}}export{o as getInteractiveContent,c as getRoleContent,l as useInteractiveChildrenNeedDescription,f as useNoInteractiveChildren};
79
+ //#endregion
80
+ export { getInteractiveContent, getRoleContent, useInteractiveChildrenNeedDescription, useNoInteractiveChildren };
@@ -1 +1,6 @@
1
- "use strict";var x=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var n=Object.prototype.hasOwnProperty;var s=(t,e)=>{for(var o in e)x(t,o,{get:e[o],enumerable:!0})},u=(t,e,o,S)=>{if(e&&typeof e=="object"||typeof e=="function")for(let p of y(e))!n.call(t,p)&&p!==o&&x(t,p,{get:()=>e[p],enumerable:!(S=m(e,p))||S.enumerable});return t};var C=t=>u(x({},"__esModule",{value:!0}),t);var d={};s(d,{StepGroup:()=>f.StepGroup,StepProvider:()=>r.StepProvider,useStepContext:()=>r.useStepContext});module.exports=C(d);var f=require("./StepGroup"),r=require("./StepContext");
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_StepContext = require('../chunk.js');
3
+
4
+ exports.StepGroup = require_StepContext.StepGroup;
5
+ exports.StepProvider = require_StepContext.StepProvider;
6
+ exports.useStepContext = require_StepContext.useStepContext;
package/lib/chunk.js ADDED
@@ -0,0 +1,111 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+ let react = require("react");
29
+ react = __toESM(react);
30
+ let react_jsx_runtime = require("react/jsx-runtime");
31
+
32
+ //#region src/StepFlow/StepGroup.tsx
33
+ /**
34
+ * Copyright IBM Corp. 2025, 2025
35
+ *
36
+ * This source code is licensed under the Apache-2.0 license found in the
37
+ * LICENSE file in the root directory of this source tree.
38
+ */
39
+ /**
40
+ * Container for steps. The children are filtered for only truthy values (via Children.toArray)
41
+ * and only the current step is returned from this component based on the `currentStep` value
42
+ * from `useStepContext`.
43
+ */
44
+ const StepGroup = ({ children }) => {
45
+ const { setTotalSteps, currentStep } = useStepContext();
46
+ const childrenArray = react.default.Children.toArray(children);
47
+ (0, react.useEffect)(() => {
48
+ setTotalSteps(childrenArray.length);
49
+ }, [childrenArray.length, setTotalSteps]);
50
+ return childrenArray[currentStep - 1];
51
+ };
52
+
53
+ //#endregion
54
+ //#region src/StepFlow/StepContext.tsx
55
+ /**
56
+ * Copyright IBM Corp. 2025, 2025
57
+ *
58
+ * This source code is licensed under the Apache-2.0 license found in the
59
+ * LICENSE file in the root directory of this source tree.
60
+ */
61
+ const StepContext = (0, react.createContext)(void 0);
62
+ const StepProvider = ({ children }) => {
63
+ const [totalSteps, setTotalSteps] = (0, react.useState)(1);
64
+ const [currentStep, setCurrentStep] = (0, react.useState)(1);
65
+ const [formState, setFormState] = (0, react.useState)({});
66
+ const context = {
67
+ formState,
68
+ setFormState,
69
+ totalSteps,
70
+ setTotalSteps,
71
+ currentStep,
72
+ handleGoToStep: (step) => setCurrentStep(step),
73
+ handleNext: () => setCurrentStep((step) => step + 1),
74
+ handlePrevious: () => setCurrentStep((step) => step - 1)
75
+ };
76
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepContext.Provider, {
77
+ value: context,
78
+ children
79
+ });
80
+ };
81
+ const useStepContext = () => {
82
+ const context = (0, react.useContext)(StepContext);
83
+ if (context === void 0) throw new Error("Context hook used outside of Step provider");
84
+ return context;
85
+ };
86
+
87
+ //#endregion
88
+ Object.defineProperty(exports, 'StepGroup', {
89
+ enumerable: true,
90
+ get: function () {
91
+ return StepGroup;
92
+ }
93
+ });
94
+ Object.defineProperty(exports, 'StepProvider', {
95
+ enumerable: true,
96
+ get: function () {
97
+ return StepProvider;
98
+ }
99
+ });
100
+ Object.defineProperty(exports, '__toESM', {
101
+ enumerable: true,
102
+ get: function () {
103
+ return __toESM;
104
+ }
105
+ });
106
+ Object.defineProperty(exports, 'useStepContext', {
107
+ enumerable: true,
108
+ get: function () {
109
+ return useStepContext;
110
+ }
111
+ });
package/lib/index.js CHANGED
@@ -1 +1,18 @@
1
- "use strict";var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var t=(f,r,p,x)=>{if(r&&typeof r=="object"||typeof r=="function")for(let m of c(r))!d.call(f,m)&&m!==p&&a(f,m,{get:()=>r[m],enumerable:!(x=b(r,m))||x.enumerable});return f},e=(f,r,p)=>(t(f,r,"default"),p&&t(p,r,"default"));var g=f=>t(a({},"__esModule",{value:!0}),f);var o={};module.exports=g(o);e(o,require("@carbon/utilities"),module.exports);e(o,require("./useNoInteractiveChildren"),module.exports);e(o,require("./StepFlow"),module.exports);
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_StepContext = require('./chunk.js');
3
+ const require_useNoInteractiveChildren_index = require('./useNoInteractiveChildren/index.js');
4
+
5
+ exports.StepGroup = require_StepContext.StepGroup;
6
+ exports.StepProvider = require_StepContext.StepProvider;
7
+ exports.getInteractiveContent = require_useNoInteractiveChildren_index.getInteractiveContent;
8
+ exports.getRoleContent = require_useNoInteractiveChildren_index.getRoleContent;
9
+ exports.useInteractiveChildrenNeedDescription = require_useNoInteractiveChildren_index.useInteractiveChildrenNeedDescription;
10
+ exports.useNoInteractiveChildren = require_useNoInteractiveChildren_index.useNoInteractiveChildren;
11
+ exports.useStepContext = require_StepContext.useStepContext;
12
+ var _carbon_utilities = require("@carbon/utilities");
13
+ Object.keys(_carbon_utilities).forEach(function (k) {
14
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
15
+ enumerable: true,
16
+ get: function () { return _carbon_utilities[k]; }
17
+ });
18
+ });
@@ -1,5 +1,85 @@
1
- "use strict";var u=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var a=(r,t)=>{for(var e in t)u(r,e,{get:t[e],enumerable:!0})},h=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of f(t))!l.call(r,o)&&o!==e&&u(r,o,{get:()=>t[o],enumerable:!(n=d(t,o))||n.enumerable});return r};var N=r=>h(u({},"__esModule",{value:!0}),r);var E={};a(E,{getInteractiveContent:()=>i,getRoleContent:()=>s,useInteractiveChildrenNeedDescription:()=>b,useNoInteractiveChildren:()=>p});module.exports=N(E);var c=require("react");function p(r,t="component should have no interactive child nodes"){(0,c.useEffect)(()=>{if(process.env.NODE_ENV==="production")return;const{current:e}=r,n=e?i(e):null;if(n){const o=`Error: ${t}.
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_StepContext = require('../chunk.js');
3
+ let react = require("react");
2
4
 
3
- Instead found: ${n.outerHTML}`;throw console.error(o),new Error(o)}},[t,r])}function b(r,t="interactive child node(s) should have an `aria-describedby` property"){(0,c.useEffect)(()=>{if(process.env.NODE_ENV==="production")return;const{current:e}=r,n=e?i(e):null;if(n&&!n.hasAttribute("aria-describedby"))throw new Error(`Error: ${t}.
5
+ //#region src/useNoInteractiveChildren/index.jsx
6
+ /**
7
+ * Copyright IBM Corp. 2016, 2026
8
+ *
9
+ * This source code is licensed under the Apache-2.0 license found in the
10
+ * LICENSE file in the root directory of this source tree.
11
+ */
12
+ function useNoInteractiveChildren(ref, message = "component should have no interactive child nodes") {
13
+ (0, react.useEffect)(() => {
14
+ if (process.env.NODE_ENV === "production") return;
15
+ const { current } = ref;
16
+ const node = current ? getInteractiveContent(current) : null;
17
+ if (node) {
18
+ const errorMessage = `Error: ${message}.\n\nInstead found: ${node.outerHTML}`;
19
+ console.error(errorMessage);
20
+ throw new Error(errorMessage);
21
+ }
22
+ }, [message, ref]);
23
+ }
24
+ function useInteractiveChildrenNeedDescription(ref, message = `interactive child node(s) should have an \`aria-describedby\` property`) {
25
+ (0, react.useEffect)(() => {
26
+ if (process.env.NODE_ENV === "production") return;
27
+ const { current } = ref;
28
+ const node = current ? getInteractiveContent(current) : null;
29
+ if (node && !node.hasAttribute("aria-describedby")) throw new Error(`Error: ${message}.\n\nInstead found: ${node.outerHTML}`);
30
+ }, [message, ref]);
31
+ }
32
+ /**
33
+ * Determines if a given DOM node has interactive content, or is itself
34
+ * interactive. It returns the interactive node if one is found
35
+ *
36
+ * @param {HTMLElement} node
37
+ * @returns {HTMLElement}
38
+ */
39
+ function getInteractiveContent(node) {
40
+ if (!node || !node.childNodes) return null;
41
+ if (isFocusable(node)) return node;
42
+ for (const childNode of node.childNodes) {
43
+ const interactiveNode = getInteractiveContent(childNode);
44
+ if (interactiveNode) return interactiveNode;
45
+ }
46
+ return null;
47
+ }
48
+ /**
49
+ * Determines if a given DOM node has a role, or has itself a role.
50
+ * It returns the node with a role if one is found
51
+ *
52
+ * @param {HTMLElement} node
53
+ * @returns {HTMLElement}
54
+ */
55
+ function getRoleContent(node) {
56
+ if (!node || !node.childNodes) return null;
57
+ if (node?.getAttribute?.("role") && node.getAttribute("role") !== "") return node;
58
+ for (const childNode of node.childNodes) {
59
+ const roleNode = getRoleContent(childNode);
60
+ if (roleNode) return roleNode;
61
+ }
62
+ return null;
63
+ }
64
+ /**
65
+ * Determines if the given element is focusable, or not
66
+ *
67
+ * @param {HTMLElement} element
68
+ * @returns {boolean}
69
+ * @see https://github.com/w3c/aria-practices/blob/0553bb51588ffa517506e2a1b2ca1422ed438c5f/examples/js/utils.js#L68
70
+ */
71
+ function isFocusable(element) {
72
+ if (element.tabIndex === void 0 || element.tabIndex < 0) return false;
73
+ if (element.disabled) return false;
74
+ switch (element.nodeName) {
75
+ case "A": return !!element.href && element.rel !== "ignore";
76
+ case "INPUT": return element.type !== "hidden";
77
+ default: return true;
78
+ }
79
+ }
4
80
 
5
- Instead found: ${n.outerHTML}`)},[t,r])}function i(r){if(!r||!r.childNodes)return null;if(v(r))return r;for(const t of r.childNodes){const e=i(t);if(e)return e}return null}function s(r){if(!r||!r.childNodes)return null;if(r?.getAttribute?.("role")&&r.getAttribute("role")!=="")return r;for(const t of r.childNodes){const e=s(t);if(e)return e}return null}function v(r){if(r.tabIndex===void 0||r.tabIndex<0||r.disabled)return!1;switch(r.nodeName){case"A":return!!r.href&&r.rel!=="ignore";case"INPUT":return r.type!=="hidden";default:return!0}}
81
+ //#endregion
82
+ exports.getInteractiveContent = getInteractiveContent;
83
+ exports.getRoleContent = getRoleContent;
84
+ exports.useInteractiveChildrenNeedDescription = useInteractiveChildrenNeedDescription;
85
+ exports.useNoInteractiveChildren = useNoInteractiveChildren;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@carbon/utilities-react",
3
3
  "description": "Utilities and helpers to drive consistency across software products using the Carbon Design System with React",
4
- "version": "0.20.0",
4
+ "version": "0.21.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "module": "es/index.js",
8
- "types": "types/index.d.ts",
8
+ "types": "es/index.d.ts",
9
9
  "repository": {
10
10
  "type": "git",
11
11
  "url": "https://github.com/carbon-design-system/carbon.git",
@@ -15,9 +15,24 @@
15
15
  "files": [
16
16
  "es",
17
17
  "lib",
18
- "types",
19
18
  "telemetry.yml"
20
19
  ],
20
+ "sideEffects": false,
21
+ "exports": {
22
+ ".": {
23
+ "types": "./es/index.d.ts",
24
+ "import": "./es/index.js",
25
+ "require": "./lib/index.js",
26
+ "default": "./es/index.js"
27
+ },
28
+ "./*": {
29
+ "types": "./es/*/index.d.ts",
30
+ "import": "./es/*/index.js",
31
+ "require": "./lib/*/index.js",
32
+ "default": "./es/*/index.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
21
36
  "keywords": [
22
37
  "ibm",
23
38
  "carbon",
@@ -30,26 +45,22 @@
30
45
  "provenance": true
31
46
  },
32
47
  "scripts": {
33
- "build:es": "esbuild ./src/**/!(*-test).{js,ts,jsx,tsx} --minify --outdir=es --target=es2020 --format=esm --define:process=process",
34
- "build:cjs": "esbuild ./src/**/!(*-test).{js,ts,jsx,tsx} --minify --outdir=lib --target=es2020 --format=cjs --define:process=process",
35
- "build:types": "tsc",
36
- "build": "yarn build:es & yarn build:cjs & yarn build:types",
37
- "watch": "yarn build:es --watch & yarn build:cjs --watch",
38
- "clean": "rimraf es lib",
48
+ "build": "yarn clean && tsdown --config tsdown.config.mts",
49
+ "watch": "tsdown --config tsdown.config.mts --watch",
50
+ "clean": "rimraf es lib types",
39
51
  "postinstall": "ibmtelemetry --config=telemetry.yml"
40
52
  },
41
53
  "peerDependencies": {
42
54
  "react": "^16.8.6 || ^17.0.1 || ^18.2.0 || ^19.0.0"
43
55
  },
44
56
  "devDependencies": {
45
- "esbuild": "^0.25.0",
46
57
  "rimraf": "^6.0.1",
47
- "typescript": "^5.7.3",
58
+ "tsdown": "^0.20.3",
48
59
  "typescript-config-carbon": "^0.9.0"
49
60
  },
50
61
  "dependencies": {
51
- "@carbon/utilities": "^0.17.0",
62
+ "@carbon/utilities": "^0.18.0",
52
63
  "@ibm/telemetry-js": "^1.6.1"
53
64
  },
54
- "gitHead": "443fbe43ff4bd1df327997b8b0b0ebeee634d002"
65
+ "gitHead": "aeaaa31889990fc76c7e0e8a29ec0bf96ce33f82"
55
66
  }
@@ -1 +0,0 @@
1
- import{jsx as x}from"react/jsx-runtime";import{useContext as a,createContext as u,useState as r}from"react";const n=u(void 0),h=({children:t})=>{const[p,d]=r(1),[s,o]=r(1),[S,c]=r({}),i={formState:S,setFormState:c,totalSteps:p,setTotalSteps:d,currentStep:s,handleGoToStep:e=>o(e),handleNext:()=>o(e=>e+1),handlePrevious:()=>o(e=>e-1)};return x(n.Provider,{value:i,children:t})},m=()=>{const t=a(n);if(t===void 0)throw new Error("Context hook used outside of Step provider");return t};export{h as StepProvider,m as useStepContext};
@@ -1 +0,0 @@
1
- import n,{useEffect as p}from"react";import{useStepContext as c}from".";const a=({children:r})=>{const{setTotalSteps:e,currentStep:o}=c(),t=n.Children.toArray(r);return p(()=>{e(t.length)},[t.length,e]),t[o-1]};export{a as StepGroup};
File without changes
@@ -1 +0,0 @@
1
- "use strict";var s=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var v=(e,t)=>{for(var n in t)s(e,n,{get:t[n],enumerable:!0})},P=(e,t,n,d)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of C(t))!f.call(e,o)&&o!==n&&s(e,o,{get:()=>t[o],enumerable:!(d=x(t,o))||d.enumerable});return e};var l=e=>P(s({},"__esModule",{value:!0}),e);var T={};v(T,{StepProvider:()=>h,useStepContext:()=>m});module.exports=l(T);var c=require("react/jsx-runtime"),r=require("react");const S=(0,r.createContext)(void 0),h=({children:e})=>{const[t,n]=(0,r.useState)(1),[d,o]=(0,r.useState)(1),[i,a]=(0,r.useState)({}),u={formState:i,setFormState:a,totalSteps:t,setTotalSteps:n,currentStep:d,handleGoToStep:p=>o(p),handleNext:()=>o(p=>p+1),handlePrevious:()=>o(p=>p-1)};return(0,c.jsx)(S.Provider,{value:u,children:e})},m=()=>{const e=(0,r.useContext)(S);if(e===void 0)throw new Error("Context hook used outside of Step provider");return e};
@@ -1 +0,0 @@
1
- "use strict";var S=Object.create;var p=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var l=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty;var f=(t,e)=>{for(var r in e)p(t,r,{get:e[r],enumerable:!0})},s=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of i(e))!m.call(t,n)&&n!==r&&p(t,n,{get:()=>e[n],enumerable:!(o=a(e,n))||o.enumerable});return t};var h=(t,e,r)=>(r=t!=null?S(l(t)):{},s(e||!t||!t.__esModule?p(r,"default",{value:t,enumerable:!0}):r,t)),d=t=>s(p({},"__esModule",{value:!0}),t);var G={};f(G,{StepGroup:()=>C});module.exports=d(G);var c=h(require("react")),u=require(".");const C=({children:t})=>{const{setTotalSteps:e,currentStep:r}=(0,u.useStepContext)(),o=c.default.Children.toArray(t);return(0,c.useEffect)(()=>{e(o.length)},[o.length,e]),o[r-1]};
@@ -1 +0,0 @@
1
- "use strict";var n=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var i=Object.prototype.hasOwnProperty;var m=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of p(t))!i.call(e,o)&&o!==r&&n(e,o,{get:()=>t[o],enumerable:!(a=S(t,o))||a.enumerable});return e};var s=e=>m(n({},"__esModule",{value:!0}),e);var c={};module.exports=s(c);
@@ -1,14 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2025, 2025
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
- import { ReactNode } from 'react';
8
- import { StepContextType } from './types';
9
- interface StepProviderProps {
10
- children: ReactNode;
11
- }
12
- export declare const StepProvider: ({ children }: StepProviderProps) => import("react/jsx-runtime").JSX.Element;
13
- export declare const useStepContext: () => StepContextType;
14
- export {};
@@ -1,17 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2025, 2025
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
- import React from 'react';
8
- interface StepGroupProps {
9
- children: React.ReactNode;
10
- }
11
- /**
12
- * Container for steps. The children are filtered for only truthy values (via Children.toArray)
13
- * and only the current step is returned from this component based on the `currentStep` value
14
- * from `useStepContext`.
15
- */
16
- export declare const StepGroup: ({ children }: StepGroupProps) => string | number | bigint | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined>;
17
- export {};
@@ -1,9 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2025, 2025
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
- export { StepGroup } from './StepGroup';
8
- export { StepProvider, useStepContext } from './StepContext';
9
- export type { StepContextType } from './types';
@@ -1,25 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2025, 2025
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
- import { Dispatch, SetStateAction } from 'react';
8
- /**
9
- * This interface should be extended by the consumer to match their own unique
10
- * use case given the fields within their own stepped experience.
11
- */
12
- interface formStateType {
13
- [key: string]: unknown;
14
- }
15
- export interface StepContextType {
16
- formState: formStateType;
17
- setFormState: Dispatch<SetStateAction<formStateType>>;
18
- totalSteps: number;
19
- setTotalSteps: Dispatch<SetStateAction<number>>;
20
- currentStep: number;
21
- handleGoToStep: (step: number) => void;
22
- handleNext: () => void;
23
- handlePrevious: () => void;
24
- }
25
- export {};
package/types/index.d.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2024
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
- export * from '@carbon/utilities';
8
- export * from './useNoInteractiveChildren';
9
- export * from './StepFlow';
@@ -1,18 +0,0 @@
1
- export function useNoInteractiveChildren(ref: any, message?: string): void;
2
- export function useInteractiveChildrenNeedDescription(ref: any, message?: string): void;
3
- /**
4
- * Determines if a given DOM node has interactive content, or is itself
5
- * interactive. It returns the interactive node if one is found
6
- *
7
- * @param {HTMLElement} node
8
- * @returns {HTMLElement}
9
- */
10
- export function getInteractiveContent(node: HTMLElement): HTMLElement;
11
- /**
12
- * Determines if a given DOM node has a role, or has itself a role.
13
- * It returns the node with a role if one is found
14
- *
15
- * @param {HTMLElement} node
16
- * @returns {HTMLElement}
17
- */
18
- export function getRoleContent(node: HTMLElement): HTMLElement;