@planningcenter/tapestry 4.9.0-rc.2 → 4.9.0-rc.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Pane.d.ts","sourceRoot":"","sources":["../../../src/components/pane/Pane.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAE,KAAK,cAAc,EAAqB,MAAM,OAAO,CAAA;AAIrE,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,CAAC,cAAc,CAAC,EAC9B,MAAM,SAAS,CAChB,GACC,SAAS,CAAA;AAEX;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,GAAG,SAAS,EACb,EAAE,gBAAgB,qBAyBlB;yBA9Be,IAAI"}
1
+ {"version":3,"file":"Pane.d.ts","sourceRoot":"","sources":["../../../src/components/pane/Pane.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAA;AAKlD,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,CAAC,cAAc,CAAC,EAC9B,MAAM,SAAS,CAChB,GACC,SAAS,CAAA;AAuBX;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,GAAG,SAAS,EACb,EAAE,gBAAgB,qBAyBlB;yBA9Be,IAAI"}
@@ -1,8 +1,28 @@
1
1
  import { useId } from '../../utilities/useId.js';
2
2
  import classNames from 'classnames';
3
- import React__default, { useState, useMemo } from 'react';
3
+ import React__default from 'react';
4
4
  import { PaneContext } from './PaneContext.js';
5
+ import { PaneHeader, hasRenderableTitle } from './PaneHeader.js';
5
6
 
7
+ /**
8
+ * Flattens Fragments so a `PaneHeader` can be found regardless of whether
9
+ * children arrive as direct JSX children or as a single Fragment value (as
10
+ * happens when `children` is passed via props, e.g. Storybook args or
11
+ * `tapestry-render`).
12
+ */
13
+ function flattenChildren(children) {
14
+ const result = [];
15
+ React__default.Children.forEach(children, (child) => {
16
+ if (React__default.isValidElement(child) && child.type === React__default.Fragment) {
17
+ const fragmentProps = child.props;
18
+ result.push(...flattenChildren(fragmentProps.children));
19
+ }
20
+ else {
21
+ result.push(child);
22
+ }
23
+ });
24
+ return result;
25
+ }
6
26
  /**
7
27
  * A decorative, static surface — a card-toned container with rounded corners
8
28
  * used to visually group related content. Renders a fixed anatomy: an
@@ -18,10 +38,10 @@ function Pane({ children, className, id, ...restProps }) {
18
38
  const paneId = id || `tds-pane-${stableId}`;
19
39
  const titleId = `${paneId}-title`;
20
40
  const combinedClassName = classNames("tds-pane", className);
21
- const [hasTitle, setHasTitle] = useState(false);
22
- const contextValue = useMemo(() => ({ registerTitle: setHasTitle, titleId }), [titleId]);
41
+ const paneHeader = flattenChildren(children).find((child) => React__default.isValidElement(child) && child.type === PaneHeader);
42
+ const hasTitle = hasRenderableTitle(paneHeader?.props.title);
23
43
  return (React__default.createElement("div", { ...restProps, "aria-labelledby": hasTitle ? titleId : undefined, className: combinedClassName, id: paneId, role: hasTitle ? "region" : undefined },
24
- React__default.createElement(PaneContext.Provider, { value: contextValue }, children)));
44
+ React__default.createElement(PaneContext.Provider, { value: { titleId } }, children)));
25
45
  }
26
46
  Pane.displayName = "Pane";
27
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"Pane.js","sources":["../../../src/components/pane/Pane.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { type HTMLAttributes, useMemo, useState } from \"react\"\n\nimport { PaneContext } from \"./PaneContext\"\n\nexport interface PaneProps {\n /** `PaneHeader` / `PaneBody` / `PaneFooter`. */\n children: React.ReactNode\n}\n\nexport type PaneElementProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n keyof PaneProps\n> &\n PaneProps\n\n/**\n * A decorative, static surface — a card-toned container with rounded corners\n * used to visually group related content. Renders a fixed anatomy: an\n * optional `PaneHeader`, a `PaneBody`, and an optional `PaneFooter`. Pane does\n * not manage layout — arrange Panes on a page, and content within one, with\n * `Flex` or another layout primitive.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-pane--docs | Storybook Documentation}\n */\nexport function Pane({\n children,\n className,\n id,\n ...restProps\n}: PaneElementProps) {\n const stableId = useId()\n const paneId = id || `tds-pane-${stableId}`\n const titleId = `${paneId}-title`\n const combinedClassName = classNames(\"tds-pane\", className)\n\n const [hasTitle, setHasTitle] = useState(false)\n const contextValue = useMemo(\n () => ({ registerTitle: setHasTitle, titleId }),\n [titleId]\n )\n\n return (\n <div\n {...restProps}\n aria-labelledby={hasTitle ? titleId : undefined}\n className={combinedClassName}\n id={paneId}\n role={hasTitle ? \"region\" : undefined}\n >\n <PaneContext.Provider value={contextValue}>\n {children}\n </PaneContext.Provider>\n </div>\n )\n}\n\nPane.displayName = \"Pane\"\n"],"names":["React"],"mappings":";;;;;AAmBA;;;;;;;;;AASG;AACG,SAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,GAAG,SAAS,EACK,EAAA;AACjB,IAAA,MAAM,QAAQ,GAAG,KAAK,EAAE;AACxB,IAAA,MAAM,MAAM,GAAG,EAAE,IAAI,CAAA,SAAA,EAAY,QAAQ,EAAE;AAC3C,IAAA,MAAM,OAAO,GAAG,CAAA,EAAG,MAAM,QAAQ;IACjC,MAAM,iBAAiB,GAAG,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC;IAE3D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAC/C,MAAM,YAAY,GAAG,OAAO,CAC1B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,EAC/C,CAAC,OAAO,CAAC,CACV;AAED,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GACM,SAAS,EAAA,iBAAA,EACI,QAAQ,GAAG,OAAO,GAAG,SAAS,EAC/C,SAAS,EAAE,iBAAiB,EAC5B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAA;AAErC,QAAAA,cAAA,CAAA,aAAA,CAAC,WAAW,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,YAAY,EAAA,EACtC,QAAQ,CACY,CACnB;AAEV;AAEA,IAAI,CAAC,WAAW,GAAG,MAAM;;;;"}
1
+ {"version":3,"file":"Pane.js","sources":["../../../src/components/pane/Pane.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { type HTMLAttributes } from \"react\"\n\nimport { PaneContext } from \"./PaneContext\"\nimport { hasRenderableTitle, PaneHeader } from \"./PaneHeader\"\n\nexport interface PaneProps {\n /** `PaneHeader` / `PaneBody` / `PaneFooter`. */\n children: React.ReactNode\n}\n\nexport type PaneElementProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n keyof PaneProps\n> &\n PaneProps\n\n/**\n * Flattens Fragments so a `PaneHeader` can be found regardless of whether\n * children arrive as direct JSX children or as a single Fragment value (as\n * happens when `children` is passed via props, e.g. Storybook args or\n * `tapestry-render`).\n */\nfunction flattenChildren(children: React.ReactNode): React.ReactNode[] {\n const result: React.ReactNode[] = []\n\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === React.Fragment) {\n const fragmentProps = child.props as { children?: React.ReactNode }\n result.push(...flattenChildren(fragmentProps.children))\n } else {\n result.push(child)\n }\n })\n\n return result\n}\n\n/**\n * A decorative, static surface — a card-toned container with rounded corners\n * used to visually group related content. Renders a fixed anatomy: an\n * optional `PaneHeader`, a `PaneBody`, and an optional `PaneFooter`. Pane does\n * not manage layout — arrange Panes on a page, and content within one, with\n * `Flex` or another layout primitive.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-pane--docs | Storybook Documentation}\n */\nexport function Pane({\n children,\n className,\n id,\n ...restProps\n}: PaneElementProps) {\n const stableId = useId()\n const paneId = id || `tds-pane-${stableId}`\n const titleId = `${paneId}-title`\n const combinedClassName = classNames(\"tds-pane\", className)\n\n const paneHeader = flattenChildren(children).find(\n (child): child is React.ReactElement<{ title?: React.ReactNode }> =>\n React.isValidElement(child) && child.type === PaneHeader\n )\n const hasTitle = hasRenderableTitle(paneHeader?.props.title)\n\n return (\n <div\n {...restProps}\n aria-labelledby={hasTitle ? titleId : undefined}\n className={combinedClassName}\n id={paneId}\n role={hasTitle ? \"region\" : undefined}\n >\n <PaneContext.Provider value={{ titleId }}>\n {children}\n </PaneContext.Provider>\n </div>\n )\n}\n\nPane.displayName = \"Pane\"\n"],"names":["React"],"mappings":";;;;;;AAoBA;;;;;AAKG;AACH,SAAS,eAAe,CAAC,QAAyB,EAAA;IAChD,MAAM,MAAM,GAAsB,EAAE;IAEpCA,cAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,KAAI;AACzC,QAAA,IAAIA,cAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAKA,cAAK,CAAC,QAAQ,EAAE;AAChE,YAAA,MAAM,aAAa,GAAG,KAAK,CAAC,KAAuC;YACnE,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACzD;aAAO;AACL,YAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACpB;AACF,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,MAAM;AACf;AAEA;;;;;;;;;AASG;AACG,SAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,GAAG,SAAS,EACK,EAAA;AACjB,IAAA,MAAM,QAAQ,GAAG,KAAK,EAAE;AACxB,IAAA,MAAM,MAAM,GAAG,EAAE,IAAI,CAAA,SAAA,EAAY,QAAQ,EAAE;AAC3C,IAAA,MAAM,OAAO,GAAG,CAAA,EAAG,MAAM,QAAQ;IACjC,MAAM,iBAAiB,GAAG,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC;IAE3D,MAAM,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC/C,CAAC,KAAK,KACJA,cAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAC3D;IACD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC;AAE5D,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAA,GACM,SAAS,EAAA,iBAAA,EACI,QAAQ,GAAG,OAAO,GAAG,SAAS,EAC/C,SAAS,EAAE,iBAAiB,EAC5B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,EAAA;AAErC,QAAAA,cAAA,CAAA,aAAA,CAAC,WAAW,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,EAAA,EACrC,QAAQ,CACY,CACnB;AAEV;AAEA,IAAI,CAAC,WAAW,GAAG,MAAM;;;;"}
@@ -1,11 +1,5 @@
1
1
  import React from "react";
2
2
  export interface PaneContextValue {
3
- /**
4
- * Called by `PaneHeader` to tell the `Pane` whether a title is rendered, so
5
- * the root can decide between a labelled `region` landmark and a plain
6
- * container.
7
- */
8
- registerTitle: (hasTitle: boolean) => void;
9
3
  titleId: string;
10
4
  }
11
5
  export declare const PaneContext: React.Context<PaneContextValue | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"PaneContext.d.ts","sourceRoot":"","sources":["../../../src/components/pane/PaneContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC1C,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,WAAW,wCAAqD,CAAA"}
1
+ {"version":3,"file":"PaneContext.d.ts","sourceRoot":"","sources":["../../../src/components/pane/PaneContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,WAAW,wCAAqD,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"PaneContext.js","sources":["../../../src/components/pane/PaneContext.tsx"],"sourcesContent":["import React from \"react\"\n\nexport interface PaneContextValue {\n /**\n * Called by `PaneHeader` to tell the `Pane` whether a title is rendered, so\n * the root can decide between a labelled `region` landmark and a plain\n * container.\n */\n registerTitle: (hasTitle: boolean) => void\n titleId: string\n}\n\nexport const PaneContext = React.createContext<PaneContextValue | null>(null)\n"],"names":["React"],"mappings":";;AAYO,MAAM,WAAW,GAAGA,cAAK,CAAC,aAAa,CAA0B,IAAI;;;;"}
1
+ {"version":3,"file":"PaneContext.js","sources":["../../../src/components/pane/PaneContext.tsx"],"sourcesContent":["import React from \"react\"\n\nexport interface PaneContextValue {\n titleId: string\n}\n\nexport const PaneContext = React.createContext<PaneContextValue | null>(null)\n"],"names":["React"],"mappings":";;AAMO,MAAM,WAAW,GAAGA,cAAK,CAAC,aAAa,CAA0B,IAAI;;;;"}
@@ -21,6 +21,12 @@ export interface PaneHeaderProps {
21
21
  title?: React.ReactNode;
22
22
  }
23
23
  export type PaneHeaderElementProps = Omit<HTMLAttributes<HTMLDivElement>, keyof PaneHeaderProps> & PaneHeaderProps;
24
+ /**
25
+ * Whether `title` produces visible heading content. Shared with `Pane` so the
26
+ * root's `role="region"` / `aria-labelledby` stays in sync with whether the
27
+ * heading actually renders.
28
+ */
29
+ export declare function hasRenderableTitle(title: React.ReactNode): boolean;
24
30
  /**
25
31
  * The header region of a `Pane` — renders the title followed by any children,
26
32
  * which should be a `PaneHeaderActions` when the pane has actions. Must be
@@ -1 +1 @@
1
- {"version":3,"file":"PaneHeader.d.ts","sourceRoot":"","sources":["../../../src/components/pane/PaneHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAE,KAAK,cAAc,EAAyB,MAAM,OAAO,CAAA;AAIzE,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,CAAA;AAEnC,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACxB;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,cAAc,CAAC,cAAc,CAAC,EAC9B,MAAM,eAAe,CACtB,GACC,eAAe,CAAA;AAEjB;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,KAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,sBAAsB,qBAsCxB;yBA5Ce,UAAU"}
1
+ {"version":3,"file":"PaneHeader.d.ts","sourceRoot":"","sources":["../../../src/components/pane/PaneHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAE,KAAK,cAAc,EAAc,MAAM,OAAO,CAAA;AAI9D,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,CAAA;AAEnC,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACxB;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,cAAc,CAAC,cAAc,CAAC,EAC9B,MAAM,eAAe,CACtB,GACC,eAAe,CAAA;AAEjB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,GAAG,OAAO,CAOlE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,KAAS,EACT,KAAK,EACL,GAAG,SAAS,EACb,EAAE,sBAAsB,qBA0BxB;yBAhCe,UAAU"}
@@ -1,8 +1,19 @@
1
1
  import { Flex } from '../flex/Flex.js';
2
2
  import classNames from 'classnames';
3
- import React__default, { useContext, useEffect } from 'react';
3
+ import React__default, { useContext } from 'react';
4
4
  import { PaneContext } from './PaneContext.js';
5
5
 
6
+ /**
7
+ * Whether `title` produces visible heading content. Shared with `Pane` so the
8
+ * root's `role="region"` / `aria-labelledby` stays in sync with whether the
9
+ * heading actually renders.
10
+ */
11
+ function hasRenderableTitle(title) {
12
+ return (title !== undefined &&
13
+ title !== null &&
14
+ title !== "" &&
15
+ typeof title !== "boolean");
16
+ }
6
17
  /**
7
18
  * The header region of a `Pane` — renders the title followed by any children,
8
19
  * which should be a `PaneHeaderActions` when the pane has actions. Must be
@@ -12,24 +23,15 @@ import { PaneContext } from './PaneContext.js';
12
23
  * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-pane--docs | Storybook Documentation}
13
24
  */
14
25
  function PaneHeader({ children, className, level = 2, title, ...restProps }) {
15
- const { registerTitle, titleId } = useContext(PaneContext) ?? {};
26
+ const { titleId } = useContext(PaneContext) ?? {};
16
27
  const combinedClassName = classNames("tds-pane-header", className);
17
28
  const Heading = `h${level}`;
18
- const hasTitle = title !== undefined &&
19
- title !== null &&
20
- title !== "" &&
21
- typeof title !== "boolean";
22
- // Let the Pane know whether it has a title to label itself with, rather than
23
- // having the Pane inspect its own children.
24
- useEffect(() => {
25
- registerTitle?.(hasTitle);
26
- return () => registerTitle?.(false);
27
- }, [hasTitle, registerTitle]);
29
+ const hasTitle = hasRenderableTitle(title);
28
30
  return (React__default.createElement(Flex, { as: "header", align: "center", gap: 2, justify: "space-between", direction: "row", wrap: "wrap", ...restProps, className: combinedClassName, role: "group" },
29
31
  hasTitle && (React__default.createElement(Heading, { className: "tds-pane-title", id: titleId }, title)),
30
32
  children));
31
33
  }
32
34
  PaneHeader.displayName = "PaneHeader";
33
35
 
34
- export { PaneHeader };
36
+ export { PaneHeader, hasRenderableTitle };
35
37
  //# sourceMappingURL=PaneHeader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PaneHeader.js","sources":["../../../src/components/pane/PaneHeader.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { Flex } from \"@components/flex\"\nimport classNames from \"classnames\"\nimport React, { type HTMLAttributes, useContext, useEffect } from \"react\"\n\nimport { PaneContext } from \"./PaneContext\"\n\nexport type PaneHeaderLevel = 2 | 3\n\nexport interface PaneHeaderProps {\n /**\n * Trailing header content, rendered after the title — typically a\n * `PaneHeaderActions` wrapping the buttons that affect the whole pane.\n */\n children?: React.ReactNode\n /**\n * Controls which heading element renders (`h2` or `h3`) so the title fits\n * the document outline wherever the Pane is nested. Visual style stays\n * constant at every level. Defaults to `2`; override to `3` when nesting a\n * Pane one level deeper in the heading outline.\n */\n level?: PaneHeaderLevel\n /**\n * The pane's title. Optional only in the documented exception — e.g. a\n * wizard step whose title already lives in a Stepper component.\n */\n title?: React.ReactNode\n}\n\nexport type PaneHeaderElementProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n keyof PaneHeaderProps\n> &\n PaneHeaderProps\n\n/**\n * The header region of a `Pane` — renders the title followed by any children,\n * which should be a `PaneHeaderActions` when the pane has actions. Must be\n * rendered inside a `Pane`.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-pane--docs | Storybook Documentation}\n */\nexport function PaneHeader({\n children,\n className,\n level = 2,\n title,\n ...restProps\n}: PaneHeaderElementProps) {\n const { registerTitle, titleId } = useContext(PaneContext) ?? {}\n const combinedClassName = classNames(\"tds-pane-header\", className)\n const Heading = `h${level}` as \"h2\" | \"h3\"\n const hasTitle =\n title !== undefined &&\n title !== null &&\n title !== \"\" &&\n typeof title !== \"boolean\"\n\n // Let the Pane know whether it has a title to label itself with, rather than\n // having the Pane inspect its own children.\n useEffect(() => {\n registerTitle?.(hasTitle)\n\n return () => registerTitle?.(false)\n }, [hasTitle, registerTitle])\n\n return (\n <Flex\n as=\"header\"\n align=\"center\"\n gap={2}\n justify=\"space-between\"\n direction=\"row\"\n wrap=\"wrap\"\n {...restProps}\n className={combinedClassName}\n role=\"group\"\n >\n {hasTitle && (\n <Heading className=\"tds-pane-title\" id={titleId}>\n {title}\n </Heading>\n )}\n {children}\n </Flex>\n )\n}\n\nPaneHeader.displayName = \"PaneHeader\"\n"],"names":["React"],"mappings":";;;;;AAoCA;;;;;;;AAOG;SACa,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,KAAK,GAAG,CAAC,EACT,KAAK,EACL,GAAG,SAAS,EACW,EAAA;AACvB,IAAA,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE;IAChE,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,EAAE,SAAS,CAAC;AAClE,IAAA,MAAM,OAAO,GAAG,CAAA,CAAA,EAAI,KAAK,EAAiB;AAC1C,IAAA,MAAM,QAAQ,GACZ,KAAK,KAAK,SAAS;AACnB,QAAA,KAAK,KAAK,IAAI;AACd,QAAA,KAAK,KAAK,EAAE;QACZ,OAAO,KAAK,KAAK,SAAS;;;IAI5B,SAAS,CAAC,MAAK;AACb,QAAA,aAAa,GAAG,QAAQ,CAAC;QAEzB,OAAO,MAAM,aAAa,GAAG,KAAK,CAAC;AACrC,IAAA,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAE7B,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EACH,EAAE,EAAC,QAAQ,EACX,KAAK,EAAC,QAAQ,EACd,GAAG,EAAE,CAAC,EACN,OAAO,EAAC,eAAe,EACvB,SAAS,EAAC,KAAK,EACf,IAAI,EAAC,MAAM,EAAA,GACP,SAAS,EACb,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAC,OAAO,EAAA;AAEX,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAC,OAAO,IAAC,SAAS,EAAC,gBAAgB,EAAC,EAAE,EAAE,OAAO,EAAA,EAC5C,KAAK,CACE,CACX;QACA,QAAQ,CACJ;AAEX;AAEA,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
1
+ {"version":3,"file":"PaneHeader.js","sources":["../../../src/components/pane/PaneHeader.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { Flex } from \"@components/flex\"\nimport classNames from \"classnames\"\nimport React, { type HTMLAttributes, useContext } from \"react\"\n\nimport { PaneContext } from \"./PaneContext\"\n\nexport type PaneHeaderLevel = 2 | 3\n\nexport interface PaneHeaderProps {\n /**\n * Trailing header content, rendered after the title — typically a\n * `PaneHeaderActions` wrapping the buttons that affect the whole pane.\n */\n children?: React.ReactNode\n /**\n * Controls which heading element renders (`h2` or `h3`) so the title fits\n * the document outline wherever the Pane is nested. Visual style stays\n * constant at every level. Defaults to `2`; override to `3` when nesting a\n * Pane one level deeper in the heading outline.\n */\n level?: PaneHeaderLevel\n /**\n * The pane's title. Optional only in the documented exception — e.g. a\n * wizard step whose title already lives in a Stepper component.\n */\n title?: React.ReactNode\n}\n\nexport type PaneHeaderElementProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n keyof PaneHeaderProps\n> &\n PaneHeaderProps\n\n/**\n * Whether `title` produces visible heading content. Shared with `Pane` so the\n * root's `role=\"region\"` / `aria-labelledby` stays in sync with whether the\n * heading actually renders.\n */\nexport function hasRenderableTitle(title: React.ReactNode): boolean {\n return (\n title !== undefined &&\n title !== null &&\n title !== \"\" &&\n typeof title !== \"boolean\"\n )\n}\n\n/**\n * The header region of a `Pane` — renders the title followed by any children,\n * which should be a `PaneHeaderActions` when the pane has actions. Must be\n * rendered inside a `Pane`.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-pane--docs | Storybook Documentation}\n */\nexport function PaneHeader({\n children,\n className,\n level = 2,\n title,\n ...restProps\n}: PaneHeaderElementProps) {\n const { titleId } = useContext(PaneContext) ?? {}\n const combinedClassName = classNames(\"tds-pane-header\", className)\n const Heading = `h${level}` as \"h2\" | \"h3\"\n const hasTitle = hasRenderableTitle(title)\n\n return (\n <Flex\n as=\"header\"\n align=\"center\"\n gap={2}\n justify=\"space-between\"\n direction=\"row\"\n wrap=\"wrap\"\n {...restProps}\n className={combinedClassName}\n role=\"group\"\n >\n {hasTitle && (\n <Heading className=\"tds-pane-title\" id={titleId}>\n {title}\n </Heading>\n )}\n {children}\n </Flex>\n )\n}\n\nPaneHeader.displayName = \"PaneHeader\"\n"],"names":["React"],"mappings":";;;;;AAoCA;;;;AAIG;AACG,SAAU,kBAAkB,CAAC,KAAsB,EAAA;IACvD,QACE,KAAK,KAAK,SAAS;AACnB,QAAA,KAAK,KAAK,IAAI;AACd,QAAA,KAAK,KAAK,EAAE;AACZ,QAAA,OAAO,KAAK,KAAK,SAAS;AAE9B;AAEA;;;;;;;AAOG;SACa,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,KAAK,GAAG,CAAC,EACT,KAAK,EACL,GAAG,SAAS,EACW,EAAA;IACvB,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,IAAI,EAAE;IACjD,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,EAAE,SAAS,CAAC;AAClE,IAAA,MAAM,OAAO,GAAG,CAAA,CAAA,EAAI,KAAK,EAAiB;AAC1C,IAAA,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC;AAE1C,IAAA,QACEA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EACH,EAAE,EAAC,QAAQ,EACX,KAAK,EAAC,QAAQ,EACd,GAAG,EAAE,CAAC,EACN,OAAO,EAAC,eAAe,EACvB,SAAS,EAAC,KAAK,EACf,IAAI,EAAC,MAAM,EAAA,GACP,SAAS,EACb,SAAS,EAAE,iBAAiB,EAC5B,IAAI,EAAC,OAAO,EAAA;AAEX,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAC,OAAO,IAAC,SAAS,EAAC,gBAAgB,EAAC,EAAE,EAAE,OAAO,EAAA,EAC5C,KAAK,CACE,CACX;QACA,QAAQ,CACJ;AAEX;AAEA,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}