@planningcenter/tapestry 4.0.0-rc.2 → 4.0.0-rc.20
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/dist/componentRegistration.js +4 -0
- package/dist/componentRegistration.js.map +1 -1
- package/dist/components/DataTable/DataTable.d.ts +42 -2
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +108 -30
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/ResultsCount.d.ts +49 -0
- package/dist/components/DataTable/ResultsCount.d.ts.map +1 -0
- package/dist/components/DataTable/ResultsCount.js +76 -0
- package/dist/components/DataTable/ResultsCount.js.map +1 -0
- package/dist/components/DataTable/TableActions.d.ts +41 -0
- package/dist/components/DataTable/TableActions.d.ts.map +1 -0
- package/dist/components/DataTable/TableActions.js +47 -0
- package/dist/components/DataTable/TableActions.js.map +1 -0
- package/dist/components/button/BaseButton.d.ts.map +1 -1
- package/dist/components/button/BaseButton.js +20 -4
- package/dist/components/button/BaseButton.js.map +1 -1
- package/dist/components/combo-box/ComboBox.js +19 -19
- package/dist/components/combo-box/ComboBox.js.map +1 -1
- package/dist/components/internal/LoadingSpinner.js +2 -2
- package/dist/components/internal/LoadingSpinner.js.map +1 -1
- package/dist/components/internal/index.d.ts +2 -0
- package/dist/components/internal/index.d.ts.map +1 -1
- package/dist/components/internal/tooltip/Tooltip.d.ts +34 -0
- package/dist/components/internal/tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/internal/tooltip/TooltipTriggerContext.d.ts +7 -0
- package/dist/components/internal/tooltip/TooltipTriggerContext.d.ts.map +1 -0
- package/dist/components/internal/tooltip/TooltipTriggerContext.js +7 -0
- package/dist/components/internal/tooltip/TooltipTriggerContext.js.map +1 -0
- package/dist/components/internal/tooltip/index.d.ts +3 -0
- package/dist/components/internal/tooltip/index.d.ts.map +1 -0
- package/dist/components/link/IconLink.d.ts +1 -1
- package/dist/components/search-input/SearchInput.d.ts +40 -0
- package/dist/components/search-input/SearchInput.d.ts.map +1 -0
- package/dist/components/search-input/SearchInput.js +75 -0
- package/dist/components/search-input/SearchInput.js.map +1 -0
- package/dist/components/search-input/index.d.ts +4 -0
- package/dist/components/search-input/index.d.ts.map +1 -0
- package/dist/index.css +164 -275
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/reactRender.css +1024 -1105
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +1024 -1105
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +2728 -2809
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.js +1 -0
- package/dist/unstable.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { type ReactNode } from "react";
|
|
2
|
+
import type { ResultsNoun } from "./ResultsCount";
|
|
3
|
+
/**
|
|
4
|
+
* A table action rendered as an `IconButton` in the button group above the
|
|
5
|
+
* table. Replaces the original RFC's `{ buttonProps; callback }` shape with a
|
|
6
|
+
* narrower, more controllable API so the design can evolve without exposing the
|
|
7
|
+
* full button surface.
|
|
8
|
+
*/
|
|
9
|
+
export type TableAction = {
|
|
10
|
+
/** Called with the keys of the currently selected rows when the action is triggered. */
|
|
11
|
+
callback?: (selectedKeys: (number | string)[]) => void;
|
|
12
|
+
/** Whether the action's button is disabled. */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** The icon rendered inside the action's icon button. */
|
|
15
|
+
icon: ReactNode;
|
|
16
|
+
/** Accessible label for the icon-only action button. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Standard click handler, invoked with the click event before `callback`. */
|
|
19
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
20
|
+
};
|
|
21
|
+
export interface TableActionsProps {
|
|
22
|
+
/** The table actions to render as an `IconButton` group. */
|
|
23
|
+
actions: TableAction[];
|
|
24
|
+
/**
|
|
25
|
+
* The noun used to describe the selection in each action's `aria-label`.
|
|
26
|
+
* See {@link ResultsNoun}.
|
|
27
|
+
*/
|
|
28
|
+
resultsNoun?: ResultsNoun;
|
|
29
|
+
/** The keys of the currently selected rows, passed to each action's `callback`. */
|
|
30
|
+
selectedKeys: (number | string)[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Renders the table actions as an `IconButton` group displayed directly after
|
|
34
|
+
* the results count, above the table. Each entry becomes an icon button whose
|
|
35
|
+
* `callback` receives the keys of the currently selected rows.
|
|
36
|
+
*/
|
|
37
|
+
export declare const TableActions: {
|
|
38
|
+
({ actions, resultsNoun, selectedKeys, }: TableActionsProps): React.JSX.Element;
|
|
39
|
+
displayName: string;
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=TableActions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableActions.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/TableActions.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,IAAI,CAAA;IACtD,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yDAAyD;IACzD,IAAI,EAAE,SAAS,CAAA;IACf,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,8EAA8E;IAC9E,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;CACrD,CAAA;AAED,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,mFAAmF;IACnF,YAAY,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAClC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY;8CAItB,iBAAiB;;CAwBnB,CAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import '../button/Button.js';
|
|
2
|
+
import '../button/DropdownButton.js';
|
|
3
|
+
import '../button/DropdownIconButton.js';
|
|
4
|
+
import { IconButton } from '../button/IconButton.js';
|
|
5
|
+
import '../button/LoadingButton.js';
|
|
6
|
+
import '../button/PageHeaderActionsDropdownButton.js';
|
|
7
|
+
import { ButtonGroup } from '../button-group/ButtonGroup.js';
|
|
8
|
+
import React__default from 'react';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Renders the table actions as an `IconButton` group displayed directly after
|
|
12
|
+
* the results count, above the table. Each entry becomes an icon button whose
|
|
13
|
+
* `callback` receives the keys of the currently selected rows.
|
|
14
|
+
*/
|
|
15
|
+
const TableActions = ({ actions, resultsNoun, selectedKeys, }) => {
|
|
16
|
+
// The count/noun suffix is the same for every table action, so compute it once
|
|
17
|
+
// here rather than per-button inside the map below.
|
|
18
|
+
const countSuffix = getTableActionCountSuffix(selectedKeys.length, resultsNoun);
|
|
19
|
+
return (React__default.createElement(ButtonGroup, { "aria-label": "Table actions" }, actions.map(({ callback, disabled, icon, label, onClick }) => (React__default.createElement(IconButton, { key: label, "aria-label": `${label}${countSuffix}`, disabled: disabled, icon: icon, onClick: (event) => {
|
|
20
|
+
onClick?.(event);
|
|
21
|
+
callback?.(selectedKeys);
|
|
22
|
+
} })))));
|
|
23
|
+
};
|
|
24
|
+
TableActions.displayName = "TableActions";
|
|
25
|
+
const numberFormatter = new Intl.NumberFormat();
|
|
26
|
+
/**
|
|
27
|
+
* The count/noun suffix appended to each table action's `aria-label` when rows
|
|
28
|
+
* are selected, e.g. `" (2 selected people)"` — so `"Email"` reads as
|
|
29
|
+
* `"Email (2 selected people)"`. Empty when nothing is selected. Falls back to
|
|
30
|
+
* the default `"result"` noun when `resultsNoun` isn't provided. Shared across
|
|
31
|
+
* every action, so it's computed once rather than per-button.
|
|
32
|
+
*/
|
|
33
|
+
function getTableActionCountSuffix(count, resultsNoun) {
|
|
34
|
+
if (!count)
|
|
35
|
+
return "";
|
|
36
|
+
const [singular, plural] = Array.isArray(resultsNoun)
|
|
37
|
+
? resultsNoun
|
|
38
|
+
: typeof resultsNoun === "string"
|
|
39
|
+
? [resultsNoun, `${resultsNoun}s`]
|
|
40
|
+
: ["result", "results"];
|
|
41
|
+
const noun = count === 1 ? singular : plural;
|
|
42
|
+
const formattedCount = numberFormatter.format(count);
|
|
43
|
+
return ` (${formattedCount} selected ${noun})`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { TableActions };
|
|
47
|
+
//# sourceMappingURL=TableActions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TableActions.js","sources":["../../../src/components/DataTable/TableActions.tsx"],"sourcesContent":["import { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport React, { type ReactNode } from \"react\"\n\nimport type { ResultsNoun } from \"./ResultsCount\"\n\n/**\n * A table action rendered as an `IconButton` in the button group above the\n * table. Replaces the original RFC's `{ buttonProps; callback }` shape with a\n * narrower, more controllable API so the design can evolve without exposing the\n * full button surface.\n */\nexport type TableAction = {\n /** Called with the keys of the currently selected rows when the action is triggered. */\n callback?: (selectedKeys: (number | string)[]) => void\n /** Whether the action's button is disabled. */\n disabled?: boolean\n /** The icon rendered inside the action's icon button. */\n icon: ReactNode\n /** Accessible label for the icon-only action button. */\n label: string\n /** Standard click handler, invoked with the click event before `callback`. */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n}\n\nexport interface TableActionsProps {\n /** The table actions to render as an `IconButton` group. */\n actions: TableAction[]\n /**\n * The noun used to describe the selection in each action's `aria-label`.\n * See {@link ResultsNoun}.\n */\n resultsNoun?: ResultsNoun\n /** The keys of the currently selected rows, passed to each action's `callback`. */\n selectedKeys: (number | string)[]\n}\n\n/**\n * Renders the table actions as an `IconButton` group displayed directly after\n * the results count, above the table. Each entry becomes an icon button whose\n * `callback` receives the keys of the currently selected rows.\n */\nexport const TableActions = ({\n actions,\n resultsNoun,\n selectedKeys,\n}: TableActionsProps) => {\n // The count/noun suffix is the same for every table action, so compute it once\n // here rather than per-button inside the map below.\n const countSuffix = getTableActionCountSuffix(\n selectedKeys.length,\n resultsNoun\n )\n\n return (\n <ButtonGroup aria-label=\"Table actions\">\n {actions.map(({ callback, disabled, icon, label, onClick }) => (\n <IconButton\n key={label}\n aria-label={`${label}${countSuffix}`}\n disabled={disabled}\n icon={icon}\n onClick={(event) => {\n onClick?.(event)\n callback?.(selectedKeys)\n }}\n />\n ))}\n </ButtonGroup>\n )\n}\n\nTableActions.displayName = \"TableActions\"\n\nconst numberFormatter = new Intl.NumberFormat()\n\n/**\n * The count/noun suffix appended to each table action's `aria-label` when rows\n * are selected, e.g. `\" (2 selected people)\"` — so `\"Email\"` reads as\n * `\"Email (2 selected people)\"`. Empty when nothing is selected. Falls back to\n * the default `\"result\"` noun when `resultsNoun` isn't provided. Shared across\n * every action, so it's computed once rather than per-button.\n */\nfunction getTableActionCountSuffix(\n count: number,\n resultsNoun: ResultsNoun | undefined\n): string {\n if (!count) return \"\"\n const [singular, plural] = Array.isArray(resultsNoun)\n ? resultsNoun\n : typeof resultsNoun === \"string\"\n ? [resultsNoun, `${resultsNoun}s`]\n : [\"result\", \"results\"]\n const noun = count === 1 ? singular : plural\n const formattedCount = numberFormatter.format(count)\n return ` (${formattedCount} selected ${noun})`\n}\n"],"names":["React"],"mappings":";;;;;;;;;AAqCA;;;;AAIG;AACI,MAAM,YAAY,GAAG,CAAC,EAC3B,OAAO,EACP,WAAW,EACX,YAAY,GACM,KAAI;;;IAGtB,MAAM,WAAW,GAAG,yBAAyB,CAC3C,YAAY,CAAC,MAAM,EACnB,WAAW,CACZ;IAED,QACEA,cAAA,CAAA,aAAA,CAAC,WAAW,EAAA,EAAA,YAAA,EAAY,eAAe,IACpC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MACxDA,6BAAC,UAAU,EAAA,EACT,GAAG,EAAE,KAAK,EAAA,YAAA,EACE,GAAG,KAAK,CAAA,EAAG,WAAW,CAAA,CAAE,EACpC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,CAAC,KAAK,KAAI;AACjB,YAAA,OAAO,GAAG,KAAK,CAAC;AAChB,YAAA,QAAQ,GAAG,YAAY,CAAC;AAC1B,QAAA,CAAC,EAAA,CACD,CACH,CAAC,CACU;AAElB;AAEA,YAAY,CAAC,WAAW,GAAG,cAAc;AAEzC,MAAM,eAAe,GAAG,IAAI,IAAI,CAAC,YAAY,EAAE;AAE/C;;;;;;AAMG;AACH,SAAS,yBAAyB,CAChC,KAAa,EACb,WAAoC,EAAA;AAEpC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,EAAE;IACrB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW;AAClD,UAAE;AACF,UAAE,OAAO,WAAW,KAAK;AACvB,cAAE,CAAC,WAAW,EAAE,CAAA,EAAG,WAAW,GAAG;AACjC,cAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;AAC3B,IAAA,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,GAAG,QAAQ,GAAG,MAAM;IAC5C,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC;AACpD,IAAA,OAAO,CAAA,EAAA,EAAK,cAAc,CAAA,UAAA,EAAa,IAAI,GAAG;AAChD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/BaseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"BaseButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/BaseButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAIlB,OAAO,EACL,kBAAkB,EAGlB,aAAa,EAEd,MAAM,6BAA6B,CAAA;AAEpC,OAAO,KAAK,EAAE,EAAE,oBAAoB,EAA0B,MAAM,OAAO,CAAA;AAI3E,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACvE,sCAAsC;IACtC,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,sCAAsC;IACtC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,+GAA+G;IAC/G,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,eAAe,GAAG,UAAU,CACnC,GACC,eAAe,CAAA;AAEjB,eAAO,MAAM,UAAU,qLA+DtB,CAAA"}
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
import LoadingSpinner from '../internal/LoadingSpinner.js';
|
|
2
|
-
import { COMPONENT_SIZE_CLASS_MAP, COMPONENT_KIND_CLASS_MAP, wrapStringWithSpan } from '../../utilities/buttonLinkShared.js';
|
|
3
2
|
import classNames from 'classnames';
|
|
4
|
-
import React__default, { forwardRef } from 'react';
|
|
3
|
+
import React__default, { forwardRef, useContext } from 'react';
|
|
4
|
+
import 'react-aria/Overlay';
|
|
5
|
+
import 'react-aria/useOverlayPosition';
|
|
6
|
+
import 'react-aria/useTooltipTrigger';
|
|
7
|
+
import 'react-stately/useTooltipTriggerState';
|
|
8
|
+
import { TooltipTriggerContext } from '../internal/tooltip/TooltipTriggerContext.js';
|
|
9
|
+
import { COMPONENT_SIZE_CLASS_MAP, COMPONENT_KIND_CLASS_MAP, wrapStringWithSpan } from '../../utilities/buttonLinkShared.js';
|
|
10
|
+
import { mergeProps } from 'react-aria/mergeProps';
|
|
11
|
+
import { mergeRefs } from 'react-aria/mergeRefs';
|
|
5
12
|
|
|
6
|
-
const BaseButton = forwardRef(({ "aria-label": ariaLabel, className, disabled = false, fullWidth, kind = "secondary", label, loading = false, loadingAriaLabel = "Loading...", prefix, size, suffix, ...restProps }, ref) => {
|
|
13
|
+
const BaseButton = forwardRef(({ "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, className, disabled = false, fullWidth, kind = "secondary", label, loading = false, loadingAriaLabel = "Loading...", prefix, size, suffix, ...restProps }, ref) => {
|
|
14
|
+
const tooltip = useContext(TooltipTriggerContext);
|
|
15
|
+
const { "aria-describedby": tooltipId, ...tooltipTriggerProps } = tooltip?.triggerProps ?? {};
|
|
16
|
+
const mergedProps = tooltip
|
|
17
|
+
? mergeProps(restProps, tooltipTriggerProps)
|
|
18
|
+
: restProps;
|
|
19
|
+
const mergedRef = tooltip
|
|
20
|
+
? mergeRefs(ref, tooltip.ref)
|
|
21
|
+
: ref;
|
|
22
|
+
const describedBy = [ariaDescribedBy, tooltipId].filter(Boolean).join(" ") || undefined;
|
|
7
23
|
const combinedClassName = classNames(kind && "tds-btn", size && size !== "md" && COMPONENT_SIZE_CLASS_MAP[size], kind && COMPONENT_KIND_CLASS_MAP[kind], fullWidth && "tds-btn--full-width", loading && "tds-btn--loading", className, { "tds-btn--prefix": prefix, "tds-btn--suffix": suffix });
|
|
8
24
|
const isDisabled = disabled || loading;
|
|
9
|
-
return (React__default.createElement("button", { type: "button", className: combinedClassName, ref:
|
|
25
|
+
return (React__default.createElement("button", { type: "button", className: combinedClassName, ref: mergedRef, ...mergedProps, "aria-busy": loading || undefined, "aria-describedby": describedBy, "aria-disabled": isDisabled || undefined, disabled: isDisabled, "aria-label": loading ? loadingAriaLabel : ariaLabel },
|
|
10
26
|
loading && React__default.createElement(LoadingSpinner, null),
|
|
11
27
|
wrapStringWithSpan(prefix),
|
|
12
28
|
loading ? React__default.createElement("span", null, label) : label,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseButton.js","sources":["../../../src/components/button/BaseButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport {\n BaseComponentProps,\n COMPONENT_KIND_CLASS_MAP,\n COMPONENT_SIZE_CLASS_MAP,\n ComponentKind,\n wrapStringWithSpan,\n} from \"@utilities/buttonLinkShared\"\nimport classNames from \"classnames\"\nimport React, { ButtonHTMLAttributes, forwardRef } from \"react\"\n\nexport interface BaseButtonProps extends Omit<BaseComponentProps, \"kind\"> {\n /** The visual style of the button. */\n kind?: ComponentKind\n /** The text content of the button. */\n label: React.ReactNode\n /** Whether the button is in a loading state. When true, the button is disabled and shows a loading spinner. */\n loading?: boolean\n /** Accessible label to use when the button is in loading state. */\n loadingAriaLabel?: string\n}\n\nexport type BaseButtonElementProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof BaseButtonProps | \"children\"\n> &\n BaseButtonProps\n\nexport const BaseButton = forwardRef<HTMLButtonElement, BaseButtonElementProps>(\n (\n {\n \"aria-label\": ariaLabel,\n className,\n disabled = false,\n fullWidth,\n kind = \"secondary\",\n label,\n loading = false,\n loadingAriaLabel = \"Loading...\",\n prefix,\n size,\n suffix,\n ...restProps\n }: BaseButtonElementProps,\n ref\n ) => {\n const combinedClassName = classNames(\n kind && \"tds-btn\",\n size && size !== \"md\" && COMPONENT_SIZE_CLASS_MAP[size],\n kind && COMPONENT_KIND_CLASS_MAP[kind],\n fullWidth && \"tds-btn--full-width\",\n loading && \"tds-btn--loading\",\n className,\n { \"tds-btn--prefix\": prefix, \"tds-btn--suffix\": suffix }\n )\n\n const isDisabled = disabled || loading\n\n return (\n <button\n type=\"button\"\n className={combinedClassName}\n ref={
|
|
1
|
+
{"version":3,"file":"BaseButton.js","sources":["../../../src/components/button/BaseButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport { TooltipTriggerContext } from \"@components/internal/tooltip/TooltipTriggerContext\"\nimport {\n BaseComponentProps,\n COMPONENT_KIND_CLASS_MAP,\n COMPONENT_SIZE_CLASS_MAP,\n ComponentKind,\n wrapStringWithSpan,\n} from \"@utilities/buttonLinkShared\"\nimport classNames from \"classnames\"\nimport React, { ButtonHTMLAttributes, forwardRef, useContext } from \"react\"\nimport { mergeProps } from \"react-aria/mergeProps\"\nimport { mergeRefs } from \"react-aria/mergeRefs\"\n\nexport interface BaseButtonProps extends Omit<BaseComponentProps, \"kind\"> {\n /** The visual style of the button. */\n kind?: ComponentKind\n /** The text content of the button. */\n label: React.ReactNode\n /** Whether the button is in a loading state. When true, the button is disabled and shows a loading spinner. */\n loading?: boolean\n /** Accessible label to use when the button is in loading state. */\n loadingAriaLabel?: string\n}\n\nexport type BaseButtonElementProps = Omit<\n ButtonHTMLAttributes<HTMLButtonElement>,\n keyof BaseButtonProps | \"children\"\n> &\n BaseButtonProps\n\nexport const BaseButton = forwardRef<HTMLButtonElement, BaseButtonElementProps>(\n (\n {\n \"aria-describedby\": ariaDescribedBy,\n \"aria-label\": ariaLabel,\n className,\n disabled = false,\n fullWidth,\n kind = \"secondary\",\n label,\n loading = false,\n loadingAriaLabel = \"Loading...\",\n prefix,\n size,\n suffix,\n ...restProps\n }: BaseButtonElementProps,\n ref\n ) => {\n const tooltip = useContext(TooltipTriggerContext)\n const { \"aria-describedby\": tooltipId, ...tooltipTriggerProps } =\n tooltip?.triggerProps ?? {}\n\n const mergedProps = tooltip\n ? mergeProps(restProps, tooltipTriggerProps)\n : restProps\n const mergedRef = tooltip\n ? mergeRefs<HTMLButtonElement>(ref, tooltip.ref)\n : ref\n const describedBy =\n [ariaDescribedBy, tooltipId].filter(Boolean).join(\" \") || undefined\n\n const combinedClassName = classNames(\n kind && \"tds-btn\",\n size && size !== \"md\" && COMPONENT_SIZE_CLASS_MAP[size],\n kind && COMPONENT_KIND_CLASS_MAP[kind],\n fullWidth && \"tds-btn--full-width\",\n loading && \"tds-btn--loading\",\n className,\n { \"tds-btn--prefix\": prefix, \"tds-btn--suffix\": suffix }\n )\n\n const isDisabled = disabled || loading\n\n return (\n <button\n type=\"button\"\n className={combinedClassName}\n ref={mergedRef}\n {...mergedProps}\n aria-busy={loading || undefined}\n aria-describedby={describedBy}\n aria-disabled={isDisabled || undefined}\n disabled={isDisabled}\n aria-label={loading ? loadingAriaLabel : ariaLabel}\n >\n {loading && <LoadingSpinner />}\n {wrapStringWithSpan(prefix)}\n {loading ? <span>{label}</span> : label}\n {wrapStringWithSpan(suffix)}\n </button>\n )\n }\n)\n\nBaseButton.displayName = \"BaseButton\"\n"],"names":["React"],"mappings":";;;;;;;;;;;;MAiCa,UAAU,GAAG,UAAU,CAClC,CACE,EACE,kBAAkB,EAAE,eAAe,EACnC,YAAY,EAAE,SAAS,EACvB,SAAS,EACT,QAAQ,GAAG,KAAK,EAChB,SAAS,EACT,IAAI,GAAG,WAAW,EAClB,KAAK,EACL,OAAO,GAAG,KAAK,EACf,gBAAgB,GAAG,YAAY,EAC/B,MAAM,EACN,IAAI,EACJ,MAAM,EACN,GAAG,SAAS,EACW,EACzB,GAAG,KACD;AACF,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,qBAAqB,CAAC;AACjD,IAAA,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,GAAG,mBAAmB,EAAE,GAC7D,OAAO,EAAE,YAAY,IAAI,EAAE;IAE7B,MAAM,WAAW,GAAG;AAClB,UAAE,UAAU,CAAC,SAAS,EAAE,mBAAmB;UACzC,SAAS;IACb,MAAM,SAAS,GAAG;UACd,SAAS,CAAoB,GAAG,EAAE,OAAO,CAAC,GAAG;UAC7C,GAAG;AACP,IAAA,MAAM,WAAW,GACf,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS;IAErE,MAAM,iBAAiB,GAAG,UAAU,CAClC,IAAI,IAAI,SAAS,EACjB,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC,EACvD,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC,EACtC,SAAS,IAAI,qBAAqB,EAClC,OAAO,IAAI,kBAAkB,EAC7B,SAAS,EACT,EAAE,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,CACzD;AAED,IAAA,MAAM,UAAU,GAAG,QAAQ,IAAI,OAAO;AAEtC,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,iBAAiB,EAC5B,GAAG,EAAE,SAAS,KACV,WAAW,EAAA,WAAA,EACJ,OAAO,IAAI,SAAS,EAAA,kBAAA,EACb,WAAW,mBACd,UAAU,IAAI,SAAS,EACtC,QAAQ,EAAE,UAAU,EAAA,YAAA,EACR,OAAO,GAAG,gBAAgB,GAAG,SAAS,EAAA;QAEjD,OAAO,IAAIA,cAAA,CAAA,aAAA,CAAC,cAAc,EAAA,IAAA,CAAG;QAC7B,kBAAkB,CAAC,MAAM,CAAC;QAC1B,OAAO,GAAGA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,EAAO,KAAK,CAAQ,GAAG,KAAK;AACtC,QAAA,kBAAkB,CAAC,MAAM,CAAC,CACpB;AAEb,CAAC;AAGH,UAAU,CAAC,WAAW,GAAG,YAAY;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import LoadingSpinner from '../internal/LoadingSpinner.js';
|
|
2
2
|
import Icon from '../../utilities/Icon.js';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
|
-
import
|
|
4
|
+
import React from 'react';
|
|
5
5
|
import { ListBoxLoadMoreItem, ComboBox as ComboBox$1, Label, Input, Button, Popover, ListBox, Text, ListBoxItem, ListBoxSection, Collection } from 'react-aria-components/ComboBox';
|
|
6
6
|
import { Group } from 'react-aria-components/Group';
|
|
7
7
|
import { Header } from 'react-aria-components/Header';
|
|
@@ -27,12 +27,12 @@ function ComboBox({ allowsEmptyCollection = true, children, className, descripti
|
|
|
27
27
|
"tds-combo-box--lg": size === "lg",
|
|
28
28
|
"tds-field--lg": size === "lg",
|
|
29
29
|
}, className);
|
|
30
|
-
const loadMoreItem = onLoadMore && (
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
const loadMoreItem = onLoadMore && (React.createElement(ListBoxLoadMoreItem, { className: "tds-combo-box-load-more", isLoading: loadingState === "loadingMore", onLoadMore: onLoadMore },
|
|
31
|
+
React.createElement("div", { "aria-label": "Loading more", role: "status" },
|
|
32
|
+
React.createElement(LoadingSpinner, null))));
|
|
33
33
|
const renderChildren = () => {
|
|
34
34
|
if (typeof children === "function") {
|
|
35
|
-
return (
|
|
35
|
+
return (React.createElement(Collection, { items: restProps.items ?? restProps.defaultItems }, children));
|
|
36
36
|
}
|
|
37
37
|
return children;
|
|
38
38
|
};
|
|
@@ -43,20 +43,20 @@ function ComboBox({ allowsEmptyCollection = true, children, className, descripti
|
|
|
43
43
|
// of function types (to allow narrower handlers like
|
|
44
44
|
// `setValue: (Key|null) => void`), which isn't assignable to RAC's
|
|
45
45
|
// single-function signature.
|
|
46
|
-
|
|
47
|
-
!hideLabel &&
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
menuTrigger !== "focus" && !readOnly && (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
? () => (
|
|
46
|
+
React.createElement(ComboBox$1, { ...restProps, allowsEmptyCollection: allowsEmptyCollection, "aria-label": hideLabel ? label : undefined, className: combinedClassName, defaultFilter: filter, isDisabled: disabled, isInvalid: invalid, isReadOnly: readOnly, isRequired: required, menuTrigger: menuTrigger, onChange: onChange },
|
|
47
|
+
!hideLabel && React.createElement(Label, { className: "tds-field-label" }, label),
|
|
48
|
+
React.createElement(Group, { className: "tds-field-control tds-combo-box-field" },
|
|
49
|
+
React.createElement(Input, { className: "tds-combo-box-input", placeholder: placeholder }),
|
|
50
|
+
menuTrigger !== "focus" && !readOnly && (React.createElement(Button, { className: "tds-combo-box-button tds-btn tds-btn--infield" },
|
|
51
|
+
React.createElement(Icon, { "aria-hidden": true, symbol: "general#down-caret" })))),
|
|
52
|
+
React.createElement(Popover, { className: "tds-combo-box-popover" },
|
|
53
|
+
React.createElement(ListBox, { className: "tds-combo-box-list", renderEmptyState: allowsEmptyCollection
|
|
54
|
+
? () => (React.createElement("div", { "aria-label": loadingState === "loading" ? "Loading" : undefined, className: "tds-combo-box-empty-state", role: loadingState === "loading" ? "status" : undefined }, loadingState === "loading" ? (React.createElement(LoadingSpinner, null)) : (resolveEmptyState(renderEmptyState))))
|
|
55
55
|
: undefined },
|
|
56
56
|
renderChildren(),
|
|
57
57
|
loadMoreItem)),
|
|
58
|
-
description && (
|
|
59
|
-
|
|
58
|
+
description && (React.createElement(Text, { className: "tds-field-description", slot: "description" },
|
|
59
|
+
React.createElement(Icon, { "aria-hidden": true, className: "tds-field-description-invalid-icon", symbol: "general#exclamation-triangle" }),
|
|
60
60
|
description))));
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
@@ -70,7 +70,7 @@ function ComboBox({ allowsEmptyCollection = true, children, className, descripti
|
|
|
70
70
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}
|
|
71
71
|
*/
|
|
72
72
|
function ComboBoxItem({ className, disabled, ...restProps }) {
|
|
73
|
-
return (
|
|
73
|
+
return (React.createElement(ListBoxItem, { ...restProps, className: classNames("tds-combo-box-list-item", className), isDisabled: disabled }));
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
76
|
* A group of related {@link ComboBoxItem}s within a {@link ComboBox}. Renders
|
|
@@ -80,8 +80,8 @@ function ComboBoxItem({ className, disabled, ...restProps }) {
|
|
|
80
80
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}
|
|
81
81
|
*/
|
|
82
82
|
function ComboBoxSection({ children, className, title, ...restProps }) {
|
|
83
|
-
return (
|
|
84
|
-
title && (
|
|
83
|
+
return (React.createElement(ListBoxSection, { ...restProps, className: classNames("tds-combo-box-list-section", className) },
|
|
84
|
+
title && (React.createElement(Header, { className: "tds-combo-box-section-header" }, title)),
|
|
85
85
|
children));
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComboBox.js","sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../field/index.css\"\nimport \"./index.css\"\n\nimport LoadingSpinner from \"@components/internal/LoadingSpinner\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React, { type ReactNode } from \"react\"\nimport {\n Button,\n Collection,\n ComboBox as AriaComboBox,\n type ComboBoxProps as AriaComboBoxProps,\n Input,\n type Key,\n Label,\n ListBox,\n ListBoxItem,\n type ListBoxItemProps,\n ListBoxLoadMoreItem,\n type ListBoxProps as AriaListBoxProps,\n ListBoxSection,\n type ListBoxSectionProps,\n Popover,\n Text,\n} from \"react-aria-components/ComboBox\"\nimport { Group } from \"react-aria-components/Group\"\nimport { Header } from \"react-aria-components/Header\"\n\nexport type ComboBoxSize = \"md\" | \"lg\"\n\nexport type ComboBoxLoadingState =\n | \"error\"\n | \"filtering\"\n | \"idle\"\n | \"loading\"\n | \"loadingMore\"\n | \"sorting\"\n\ntype ComboBoxChildren<T extends object> = NonNullable<\n AriaListBoxProps<T>[\"children\"]\n>\n\nexport interface ComboBoxProps<T extends object = object> {\n /** The contents of the listbox. */\n children: ComboBoxChildren<T>\n /** Helper text displayed below the component. Styled as error text when `invalid` is `true`. */\n description?: ReactNode\n /** Disables the field and trigger button. */\n disabled?: boolean\n /** Custom filter function for determining if an item should appear in the list. */\n filter?: (textValue: string, inputValue: string) => boolean\n /** If `true`, the `label` text is rendered as an `aria-label` instead of a visible label element. */\n hideLabel?: boolean\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** Accessible label for the field. */\n label: string\n /**\n * Async loading state for the listbox.\n * - `\"loading\"`: while the collection is empty, replaces the empty state with a spinner.\n * - `\"loadingMore\"`: shows an inline spinner at the bottom of the listbox (use with `onLoadMore`).\n * - Other values render as `\"idle\"`.\n */\n loadingState?: ComboBoxLoadingState\n /**\n * The interaction that opens the popover.\n * - `\"input\"`: opens when the user enters text in the input.\n * - `\"focus\"`: opens when the user focuses (via click or keyboard) into the input.\n * - `\"manual\"`: opens only via the trigger button or arrow keys.\n * @default \"focus\"\n */\n menuTrigger?: \"focus\" | \"input\" | \"manual\"\n /**\n * Called when the selected value(s) change.\n * Receives `Key[]` when `selectionMode` is `\"multiple\"`, otherwise `Key | null`.\n */\n onChange?: ((value: Key | null) => void) | ((value: Key[]) => void)\n /** Called when the user scrolls near the bottom of the listbox. Pair with `loadingState` for infinite scroll. */\n onLoadMore?: () => void\n /** Placeholder text for the input. */\n placeholder?: string\n /** If `true`, allows the value to be read but not changed. */\n readOnly?: boolean\n /** Content to display when there are no items in the list. Defaults to \"No results\". */\n renderEmptyState?: ReactNode | (() => ReactNode)\n /** If `true`, appends an asterisk at the end of the label text. */\n required?: boolean\n /** The size of the combo box. */\n size?: ComboBoxSize\n}\n\ntype AriaComboBoxPropsToOmit = \"slot\"\n\ntype AriaComboBoxPropsToInclude =\n | \"allowsEmptyCollection\"\n | \"defaultInputValue\"\n | \"defaultItems\"\n | \"defaultValue\"\n | \"disabledKeys\"\n | \"inputValue\"\n | \"items\"\n | \"name\"\n | \"onInputChange\"\n | \"selectionMode\"\n | \"value\"\n\nexport type ComboBoxElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n AriaComboBoxProps<T, \"single\" | \"multiple\">,\n ComboBoxProps<T>,\n AriaComboBoxPropsToOmit,\n AriaComboBoxPropsToInclude\n >\n\nfunction resolveEmptyState(value: ReactNode | (() => ReactNode)): ReactNode {\n return typeof value === \"function\" ? value() : value\n}\n\n/**\n * A combo box combines a text input with a filterable popover\n * listbox, allowing users to type to search and select from a list of options.\n *\n * It supports both single and multiple selection (`selectionMode`), custom filtering,\n * and asynchronous data loading with infinite scroll capabilities (`loadingState` and `onLoadMore`).\n * Collections can be either static or dynamic, managed via the `children`, `items`,\n * or `defaultItems` props. To construct the dropdown list, compose this component\n * with `ComboBoxItem` for individual options and `ComboBoxSection` for grouping.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBox<T extends object>({\n allowsEmptyCollection = true,\n children,\n className,\n description,\n disabled,\n filter,\n hideLabel,\n invalid,\n label,\n loadingState,\n menuTrigger = \"focus\",\n onChange,\n onLoadMore,\n placeholder,\n readOnly,\n renderEmptyState = \"No results\",\n required,\n size = \"md\",\n ...restProps\n}: ComboBoxElementProps<T>) {\n const combinedClassName = classNames(\n \"tds-field tds-combo-box\",\n {\n \"tds-combo-box--lg\": size === \"lg\",\n \"tds-field--lg\": size === \"lg\",\n },\n className\n )\n\n const loadMoreItem = onLoadMore && (\n <ListBoxLoadMoreItem\n className=\"tds-combo-box-load-more\"\n isLoading={loadingState === \"loadingMore\"}\n onLoadMore={onLoadMore}\n >\n <div aria-label=\"Loading more\" role=\"status\">\n <LoadingSpinner />\n </div>\n </ListBoxLoadMoreItem>\n )\n\n const renderChildren = () => {\n if (typeof children === \"function\") {\n return (\n <Collection items={restProps.items ?? restProps.defaultItems}>\n {children}\n </Collection>\n )\n }\n return children\n }\n\n return (\n // React Aria's ComboBox is generic over selection mode (M). We instantiate\n // it with the union \"single\" | \"multiple\" so value/defaultValue/selectionMode\n // accept both shapes. onChange still needs a cast because our type is a union\n // of function types (to allow narrower handlers like\n // `setValue: (Key|null) => void`), which isn't assignable to RAC's\n // single-function signature.\n <AriaComboBox<T, \"single\" | \"multiple\">\n {...restProps}\n allowsEmptyCollection={allowsEmptyCollection}\n aria-label={hideLabel ? label : undefined}\n className={combinedClassName}\n defaultFilter={filter}\n isDisabled={disabled}\n isInvalid={invalid}\n isReadOnly={readOnly}\n isRequired={required}\n menuTrigger={menuTrigger}\n onChange={onChange as (value: Key | Key[] | null) => void}\n >\n {!hideLabel && <Label className=\"tds-field-label\">{label}</Label>}\n <Group className=\"tds-field-control tds-combo-box-field\">\n <Input className=\"tds-combo-box-input\" placeholder={placeholder} />\n {menuTrigger !== \"focus\" && !readOnly && (\n <Button className=\"tds-combo-box-button tds-btn tds-btn--infield\">\n <Icon aria-hidden symbol=\"general#down-caret\" />\n </Button>\n )}\n </Group>\n <Popover className=\"tds-combo-box-popover\">\n <ListBox\n className=\"tds-combo-box-list\"\n renderEmptyState={\n allowsEmptyCollection\n ? () => (\n <div\n aria-label={\n loadingState === \"loading\" ? \"Loading\" : undefined\n }\n className=\"tds-combo-box-empty-state\"\n role={loadingState === \"loading\" ? \"status\" : undefined}\n >\n {loadingState === \"loading\" ? (\n <LoadingSpinner />\n ) : (\n resolveEmptyState(renderEmptyState)\n )}\n </div>\n )\n : undefined\n }\n >\n {renderChildren()}\n {loadMoreItem}\n </ListBox>\n </Popover>\n {description && (\n <Text className=\"tds-field-description\" slot=\"description\">\n <Icon\n aria-hidden\n className=\"tds-field-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </Text>\n )}\n </AriaComboBox>\n )\n}\n\nexport interface ComboBoxItemProps {\n /** Disables the item. */\n disabled?: boolean\n}\n\ntype AriaListBoxItemPropsToOmit = \"isDisabled\"\n\ntype AriaListBoxItemPropsToInclude = \"onAction\" | \"textValue\" | \"value\"\n\nexport type ComboBoxItemElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxItemProps<T>,\n ComboBoxItemProps,\n AriaListBoxItemPropsToOmit,\n AriaListBoxItemPropsToInclude\n >\n\n/**\n * A selectable option within a {@link ComboBox}. Renders as a listbox item.\n *\n * Provide an `id` (or `key` when rendering from a collection) to identify the\n * option, and `textValue` when the visible children are not plain text so\n * type-ahead and screen readers have a stable label to use.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxItem<T extends object>({\n className,\n disabled,\n ...restProps\n}: ComboBoxItemElementProps<T>) {\n return (\n <ListBoxItem\n {...restProps}\n className={classNames(\"tds-combo-box-list-item\", className)}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface ComboBoxSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /** Optional heading text rendered above the section's items. */\n title?: string\n}\n\ntype AriaListBoxSectionPropsToInclude = \"dependencies\"\n\nexport type ComboBoxSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxSectionProps<T>,\n ComboBoxSectionProps,\n never,\n AriaListBoxSectionPropsToInclude\n >\n\n/**\n * A group of related {@link ComboBoxItem}s within a {@link ComboBox}. Renders\n * an optional `title` heading above its items.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: ComboBoxSectionElementProps<T>) {\n return (\n <ListBoxSection\n {...restProps}\n className={classNames(\"tds-combo-box-list-section\", className)}\n >\n {title && (\n <Header className=\"tds-combo-box-section-header\">{title}</Header>\n )}\n {children}\n </ListBoxSection>\n )\n}\n"],"names":["React","AriaComboBox"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComboBox.js","sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../field/index.css\"\nimport \"./index.css\"\n\nimport LoadingSpinner from \"@components/internal/LoadingSpinner\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React, { type ReactNode } from \"react\"\nimport {\n Button,\n Collection,\n ComboBox as AriaComboBox,\n type ComboBoxProps as AriaComboBoxProps,\n Input,\n type Key,\n Label,\n ListBox,\n ListBoxItem,\n type ListBoxItemProps,\n ListBoxLoadMoreItem,\n type ListBoxProps as AriaListBoxProps,\n ListBoxSection,\n type ListBoxSectionProps,\n Popover,\n Text,\n} from \"react-aria-components/ComboBox\"\nimport { Group } from \"react-aria-components/Group\"\nimport { Header } from \"react-aria-components/Header\"\n\nexport type ComboBoxSize = \"md\" | \"lg\"\n\nexport type ComboBoxLoadingState =\n | \"error\"\n | \"filtering\"\n | \"idle\"\n | \"loading\"\n | \"loadingMore\"\n | \"sorting\"\n\ntype ComboBoxChildren<T extends object> = NonNullable<\n AriaListBoxProps<T>[\"children\"]\n>\n\nexport interface ComboBoxProps<T extends object = object> {\n /** The contents of the listbox. */\n children: ComboBoxChildren<T>\n /** Helper text displayed below the component. Styled as error text when `invalid` is `true`. */\n description?: ReactNode\n /** Disables the field and trigger button. */\n disabled?: boolean\n /** Custom filter function for determining if an item should appear in the list. */\n filter?: (textValue: string, inputValue: string) => boolean\n /** If `true`, the `label` text is rendered as an `aria-label` instead of a visible label element. */\n hideLabel?: boolean\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** Accessible label for the field. */\n label: string\n /**\n * Async loading state for the listbox.\n * - `\"loading\"`: while the collection is empty, replaces the empty state with a spinner.\n * - `\"loadingMore\"`: shows an inline spinner at the bottom of the listbox (use with `onLoadMore`).\n * - Other values render as `\"idle\"`.\n */\n loadingState?: ComboBoxLoadingState\n /**\n * The interaction that opens the popover.\n * - `\"input\"`: opens when the user enters text in the input.\n * - `\"focus\"`: opens when the user focuses (via click or keyboard) into the input.\n * - `\"manual\"`: opens only via the trigger button or arrow keys.\n * @default \"focus\"\n */\n menuTrigger?: \"focus\" | \"input\" | \"manual\"\n /**\n * Called when the selected value(s) change.\n * Receives `Key[]` when `selectionMode` is `\"multiple\"`, otherwise `Key | null`.\n */\n onChange?: ((value: Key | null) => void) | ((value: Key[]) => void)\n /** Called when the user scrolls near the bottom of the listbox. Pair with `loadingState` for infinite scroll. */\n onLoadMore?: () => void\n /** Placeholder text for the input. */\n placeholder?: string\n /** If `true`, allows the value to be read but not changed. */\n readOnly?: boolean\n /** Content to display when there are no items in the list. Defaults to \"No results\". */\n renderEmptyState?: ReactNode | (() => ReactNode)\n /** If `true`, appends an asterisk at the end of the label text. */\n required?: boolean\n /** The size of the combo box. */\n size?: ComboBoxSize\n}\n\ntype AriaComboBoxPropsToOmit = \"slot\"\n\ntype AriaComboBoxPropsToInclude =\n | \"allowsEmptyCollection\"\n | \"defaultInputValue\"\n | \"defaultItems\"\n | \"defaultValue\"\n | \"disabledKeys\"\n | \"inputValue\"\n | \"items\"\n | \"name\"\n | \"onInputChange\"\n | \"selectionMode\"\n | \"value\"\n\nexport type ComboBoxElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n AriaComboBoxProps<T, \"single\" | \"multiple\">,\n ComboBoxProps<T>,\n AriaComboBoxPropsToOmit,\n AriaComboBoxPropsToInclude\n >\n\nfunction resolveEmptyState(value: ReactNode | (() => ReactNode)): ReactNode {\n return typeof value === \"function\" ? value() : value\n}\n\n/**\n * A combo box combines a text input with a filterable popover\n * listbox, allowing users to type to search and select from a list of options.\n *\n * It supports both single and multiple selection (`selectionMode`), custom filtering,\n * and asynchronous data loading with infinite scroll capabilities (`loadingState` and `onLoadMore`).\n * Collections can be either static or dynamic, managed via the `children`, `items`,\n * or `defaultItems` props. To construct the dropdown list, compose this component\n * with `ComboBoxItem` for individual options and `ComboBoxSection` for grouping.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBox<T extends object>({\n allowsEmptyCollection = true,\n children,\n className,\n description,\n disabled,\n filter,\n hideLabel,\n invalid,\n label,\n loadingState,\n menuTrigger = \"focus\",\n onChange,\n onLoadMore,\n placeholder,\n readOnly,\n renderEmptyState = \"No results\",\n required,\n size = \"md\",\n ...restProps\n}: ComboBoxElementProps<T>) {\n const combinedClassName = classNames(\n \"tds-field tds-combo-box\",\n {\n \"tds-combo-box--lg\": size === \"lg\",\n \"tds-field--lg\": size === \"lg\",\n },\n className\n )\n\n const loadMoreItem = onLoadMore && (\n <ListBoxLoadMoreItem\n className=\"tds-combo-box-load-more\"\n isLoading={loadingState === \"loadingMore\"}\n onLoadMore={onLoadMore}\n >\n <div aria-label=\"Loading more\" role=\"status\">\n <LoadingSpinner />\n </div>\n </ListBoxLoadMoreItem>\n )\n\n const renderChildren = () => {\n if (typeof children === \"function\") {\n return (\n <Collection items={restProps.items ?? restProps.defaultItems}>\n {children}\n </Collection>\n )\n }\n return children\n }\n\n return (\n // React Aria's ComboBox is generic over selection mode (M). We instantiate\n // it with the union \"single\" | \"multiple\" so value/defaultValue/selectionMode\n // accept both shapes. onChange still needs a cast because our type is a union\n // of function types (to allow narrower handlers like\n // `setValue: (Key|null) => void`), which isn't assignable to RAC's\n // single-function signature.\n <AriaComboBox<T, \"single\" | \"multiple\">\n {...restProps}\n allowsEmptyCollection={allowsEmptyCollection}\n aria-label={hideLabel ? label : undefined}\n className={combinedClassName}\n defaultFilter={filter}\n isDisabled={disabled}\n isInvalid={invalid}\n isReadOnly={readOnly}\n isRequired={required}\n menuTrigger={menuTrigger}\n onChange={onChange as (value: Key | Key[] | null) => void}\n >\n {!hideLabel && <Label className=\"tds-field-label\">{label}</Label>}\n <Group className=\"tds-field-control tds-combo-box-field\">\n <Input className=\"tds-combo-box-input\" placeholder={placeholder} />\n {menuTrigger !== \"focus\" && !readOnly && (\n <Button className=\"tds-combo-box-button tds-btn tds-btn--infield\">\n <Icon aria-hidden symbol=\"general#down-caret\" />\n </Button>\n )}\n </Group>\n <Popover className=\"tds-combo-box-popover\">\n <ListBox\n className=\"tds-combo-box-list\"\n renderEmptyState={\n allowsEmptyCollection\n ? () => (\n <div\n aria-label={\n loadingState === \"loading\" ? \"Loading\" : undefined\n }\n className=\"tds-combo-box-empty-state\"\n role={loadingState === \"loading\" ? \"status\" : undefined}\n >\n {loadingState === \"loading\" ? (\n <LoadingSpinner />\n ) : (\n resolveEmptyState(renderEmptyState)\n )}\n </div>\n )\n : undefined\n }\n >\n {renderChildren()}\n {loadMoreItem}\n </ListBox>\n </Popover>\n {description && (\n <Text className=\"tds-field-description\" slot=\"description\">\n <Icon\n aria-hidden\n className=\"tds-field-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </Text>\n )}\n </AriaComboBox>\n )\n}\n\nexport interface ComboBoxItemProps {\n /** Disables the item. */\n disabled?: boolean\n}\n\ntype AriaListBoxItemPropsToOmit = \"isDisabled\"\n\ntype AriaListBoxItemPropsToInclude = \"onAction\" | \"textValue\" | \"value\"\n\nexport type ComboBoxItemElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxItemProps<T>,\n ComboBoxItemProps,\n AriaListBoxItemPropsToOmit,\n AriaListBoxItemPropsToInclude\n >\n\n/**\n * A selectable option within a {@link ComboBox}. Renders as a listbox item.\n *\n * Provide an `id` (or `key` when rendering from a collection) to identify the\n * option, and `textValue` when the visible children are not plain text so\n * type-ahead and screen readers have a stable label to use.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxItem<T extends object>({\n className,\n disabled,\n ...restProps\n}: ComboBoxItemElementProps<T>) {\n return (\n <ListBoxItem\n {...restProps}\n className={classNames(\"tds-combo-box-list-item\", className)}\n isDisabled={disabled}\n />\n )\n}\n\nexport interface ComboBoxSectionProps {\n /** The items rendered within the section. */\n children: ReactNode\n /** Optional heading text rendered above the section's items. */\n title?: string\n}\n\ntype AriaListBoxSectionPropsToInclude = \"dependencies\"\n\nexport type ComboBoxSectionElementProps<T extends object = object> =\n CombineAriaPropsWithCustomProps<\n ListBoxSectionProps<T>,\n ComboBoxSectionProps,\n never,\n AriaListBoxSectionPropsToInclude\n >\n\n/**\n * A group of related {@link ComboBoxItem}s within a {@link ComboBox}. Renders\n * an optional `title` heading above its items.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-combobox--docs | Storybook Documentation}\n */\nexport function ComboBoxSection<T extends object>({\n children,\n className,\n title,\n ...restProps\n}: ComboBoxSectionElementProps<T>) {\n return (\n <ListBoxSection\n {...restProps}\n className={classNames(\"tds-combo-box-list-section\", className)}\n >\n {title && (\n <Header className=\"tds-combo-box-section-header\">{title}</Header>\n )}\n {children}\n </ListBoxSection>\n )\n}\n"],"names":["AriaComboBox"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
3
|
function LoadingSpinner() {
|
|
4
|
-
return
|
|
4
|
+
return React.createElement("div", { className: "tds-loading-spinner" });
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export { LoadingSpinner as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingSpinner.js","sources":["../../../src/components/internal/LoadingSpinner.tsx"],"sourcesContent":["import \"./LoadingSpinner.css\"\n\nimport React from \"react\"\n\nexport default function LoadingSpinner() {\n return <div className=\"tds-loading-spinner\" />\n}\n"],"names":[
|
|
1
|
+
{"version":3,"file":"LoadingSpinner.js","sources":["../../../src/components/internal/LoadingSpinner.tsx"],"sourcesContent":["import \"./LoadingSpinner.css\"\n\nimport React from \"react\"\n\nexport default function LoadingSpinner() {\n return <div className=\"tds-loading-spinner\" />\n}\n"],"names":[],"mappings":";;AAIc,SAAU,cAAc,GAAA;AACpC,IAAA,OAAO,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,qBAAqB,GAAG;AAChD;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/internal/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/internal/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAE7C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,cAAc,EAAE,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { type ReactElement } from "react";
|
|
2
|
+
import { type Placement } from "react-aria/useOverlayPosition";
|
|
3
|
+
export interface TooltipProps {
|
|
4
|
+
/**
|
|
5
|
+
* A single `BaseButton`-derived element (e.g. `IconButton`, `Button`) to
|
|
6
|
+
* act as the trigger. Must be exactly one trigger — nothing enforces this
|
|
7
|
+
* at runtime, so a fragment with more than one child would silently hand
|
|
8
|
+
* every child the same ref and trigger props.
|
|
9
|
+
*/
|
|
10
|
+
children: ReactElement;
|
|
11
|
+
/**
|
|
12
|
+
* The hint text. Must add information beyond the trigger's accessible name
|
|
13
|
+
* (e.g. its `aria-label` or visible label) — `aria-describedby` wires this
|
|
14
|
+
* content to the trigger unconditionally, so duplicating the accessible
|
|
15
|
+
* name here causes it to be announced twice by screen readers.
|
|
16
|
+
*/
|
|
17
|
+
content: string;
|
|
18
|
+
/** Where the tooltip renders relative to the trigger. Default `'bottom start'`. */
|
|
19
|
+
placement?: Placement;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Shows a short hover/focus hint next to a trigger. Built from React Aria's
|
|
23
|
+
* tooltip hooks rather than `react-aria-components`'s `<Tooltip>`, because
|
|
24
|
+
* that component unmounts its content entirely while closed, so a screen
|
|
25
|
+
* reader's virtual cursor never gets access to the description unless real
|
|
26
|
+
* DOM focus lands on the trigger. This keeps the tooltip content always
|
|
27
|
+
* mounted and wires `aria-describedby` unconditionally, toggling only CSS
|
|
28
|
+
* visibility.
|
|
29
|
+
*/
|
|
30
|
+
export declare function Tooltip({ children, content, placement, }: TooltipProps): React.JSX.Element;
|
|
31
|
+
export declare namespace Tooltip {
|
|
32
|
+
var displayName: string;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=Tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/tooltip/Tooltip.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,KAAK,YAAY,EAAiB,MAAM,OAAO,CAAA;AAE/D,OAAO,EACL,KAAK,SAAS,EAEf,MAAM,+BAA+B,CAAA;AAMtC,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,QAAQ,EAAE,YAAY,CAAA;IACtB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,OAAO,EACP,SAA0B,GAC3B,EAAE,YAAY,qBA+Cd;yBAnDe,OAAO"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type HTMLAttributes, type RefObject } from "react";
|
|
2
|
+
/** Carries `<Tooltip>`'s trigger wiring down to the rendered button, via `BaseButton`. */
|
|
3
|
+
export declare const TooltipTriggerContext: import("react").Context<{
|
|
4
|
+
ref: RefObject<HTMLButtonElement>;
|
|
5
|
+
triggerProps: HTMLAttributes<HTMLButtonElement>;
|
|
6
|
+
} | null>;
|
|
7
|
+
//# sourceMappingURL=TooltipTriggerContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TooltipTriggerContext.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/tooltip/TooltipTriggerContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE1E,0FAA0F;AAC1F,eAAO,MAAM,qBAAqB;SAC3B,SAAS,CAAC,iBAAiB,CAAC;kBACnB,cAAc,CAAC,iBAAiB,CAAC;SAClC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/** Carries `<Tooltip>`'s trigger wiring down to the rendered button, via `BaseButton`. */
|
|
4
|
+
const TooltipTriggerContext = createContext(null);
|
|
5
|
+
|
|
6
|
+
export { TooltipTriggerContext };
|
|
7
|
+
//# sourceMappingURL=TooltipTriggerContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TooltipTriggerContext.js","sources":["../../../../src/components/internal/tooltip/TooltipTriggerContext.ts"],"sourcesContent":["import { createContext, type HTMLAttributes, type RefObject } from \"react\"\n\n/** Carries `<Tooltip>`'s trigger wiring down to the rendered button, via `BaseButton`. */\nexport const TooltipTriggerContext = createContext<{\n ref: RefObject<HTMLButtonElement>\n triggerProps: HTMLAttributes<HTMLButtonElement>\n} | null>(null)\n"],"names":[],"mappings":";;AAEA;MACa,qBAAqB,GAAG,aAAa,CAGxC,IAAI;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/tooltip/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -25,6 +25,7 @@ export declare const IconLink: React.ForwardRefExoticComponent<Omit<{
|
|
|
25
25
|
style?: React.CSSProperties | undefined;
|
|
26
26
|
title?: string | undefined | undefined;
|
|
27
27
|
className?: string | undefined | undefined;
|
|
28
|
+
content?: string | undefined | undefined;
|
|
28
29
|
type?: string | undefined | undefined;
|
|
29
30
|
defaultChecked?: boolean | undefined | undefined;
|
|
30
31
|
defaultValue?: string | number | readonly string[] | undefined;
|
|
@@ -46,7 +47,6 @@ export declare const IconLink: React.ForwardRefExoticComponent<Omit<{
|
|
|
46
47
|
radioGroup?: string | undefined | undefined;
|
|
47
48
|
role?: React.AriaRole | undefined;
|
|
48
49
|
about?: string | undefined | undefined;
|
|
49
|
-
content?: string | undefined | undefined;
|
|
50
50
|
datatype?: string | undefined | undefined;
|
|
51
51
|
inlist?: any;
|
|
52
52
|
property?: string | undefined | undefined;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import "./index.css";
|
|
2
|
+
import React, { type InputHTMLAttributes } from "react";
|
|
3
|
+
export type SearchInputSize = "lg" | "md";
|
|
4
|
+
interface SearchInputBaseProps {
|
|
5
|
+
/** Helper text below the input. Styled as an error when `invalid`. */
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
/** Triggers invalid state (error border, error description, aria-invalid). */
|
|
8
|
+
invalid?: boolean;
|
|
9
|
+
/** Visual size — cascades to the icon, input, and clear button via Field's font-size custom property. Defaults to 'md'. */
|
|
10
|
+
size?: SearchInputSize;
|
|
11
|
+
}
|
|
12
|
+
interface SearchInputWithLabel extends SearchInputBaseProps {
|
|
13
|
+
"aria-labelledby"?: never;
|
|
14
|
+
/** If true, the label is visually hidden but remains in the DOM/AT tree. */
|
|
15
|
+
hideLabel?: boolean;
|
|
16
|
+
/** The visible label. */
|
|
17
|
+
label: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
interface SearchInputWithAriaLabelledBy extends SearchInputBaseProps {
|
|
20
|
+
"aria-labelledby": string;
|
|
21
|
+
hideLabel?: never;
|
|
22
|
+
label?: never;
|
|
23
|
+
}
|
|
24
|
+
export type SearchInputProps = SearchInputWithAriaLabelledBy | SearchInputWithLabel;
|
|
25
|
+
/**
|
|
26
|
+
* Combines standard HTML input attributes with SearchInput's own props.
|
|
27
|
+
* `type` is fixed to "search" and not exposed; `size` is redefined above.
|
|
28
|
+
*/
|
|
29
|
+
export type SearchInputElementProps = Omit<InputHTMLAttributes<HTMLInputElement>, keyof SearchInputProps | "size" | "type"> & SearchInputProps;
|
|
30
|
+
/**
|
|
31
|
+
* A search-specific input with a leading search icon and a trailing clear
|
|
32
|
+
* ("x") button, built on `type="search"`. Composes `Field` directly for
|
|
33
|
+
* label, description, and state layout.
|
|
34
|
+
*
|
|
35
|
+
* @component
|
|
36
|
+
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-searchinput--docs | Storybook Documentation}
|
|
37
|
+
*/
|
|
38
|
+
export declare const SearchInput: React.ForwardRefExoticComponent<SearchInputElementProps & React.RefAttributes<HTMLInputElement>>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=SearchInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchInput.d.ts","sourceRoot":"","sources":["../../../src/components/search-input/SearchInput.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAOpB,OAAO,KAAK,EAAE,EAEZ,KAAK,mBAAmB,EAGzB,MAAM,OAAO,CAAA;AAEd,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,CAAA;AAEzC,UAAU,oBAAoB;IAC5B,sEAAsE;IACtE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2HAA2H;IAC3H,IAAI,CAAC,EAAE,eAAe,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,oBAAoB;IACzD,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yBAAyB;IACzB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,6BAA8B,SAAQ,oBAAoB;IAClE,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,gBAAgB,GACxB,6BAA6B,GAC7B,oBAAoB,CAAA;AAExB;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,CACzC,GACC,gBAAgB,CAAA;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,kGAiItB,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import '../button/Button.js';
|
|
2
|
+
import '../button/DropdownButton.js';
|
|
3
|
+
import '../button/DropdownIconButton.js';
|
|
4
|
+
import { IconButton } from '../button/IconButton.js';
|
|
5
|
+
import '../button/LoadingButton.js';
|
|
6
|
+
import '../button/PageHeaderActionsDropdownButton.js';
|
|
7
|
+
import { Field } from '../field/Field.js';
|
|
8
|
+
import Icon from '../../utilities/Icon.js';
|
|
9
|
+
import { useId } from '../../utilities/useId.js';
|
|
10
|
+
import classNames from 'classnames';
|
|
11
|
+
import React__default, { forwardRef, useRef, useState } from 'react';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A search-specific input with a leading search icon and a trailing clear
|
|
15
|
+
* ("x") button, built on `type="search"`. Composes `Field` directly for
|
|
16
|
+
* label, description, and state layout.
|
|
17
|
+
*
|
|
18
|
+
* @component
|
|
19
|
+
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-searchinput--docs | Storybook Documentation}
|
|
20
|
+
*/
|
|
21
|
+
const SearchInput = forwardRef(function SearchInput({ "aria-labelledby": ariaLabelledBy, className, defaultValue, description, disabled, hideLabel, id, invalid, label, onChange, onKeyDown, readOnly, size = "md", value, ...restProps }, ref) {
|
|
22
|
+
const innerRef = useRef(null);
|
|
23
|
+
const setRefs = (node) => {
|
|
24
|
+
innerRef.current = node;
|
|
25
|
+
if (typeof ref === "function")
|
|
26
|
+
ref(node);
|
|
27
|
+
else if (ref) {
|
|
28
|
+
ref.current = node;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
const stableId = useId();
|
|
32
|
+
const inputId = id || `tds-search-input-${stableId}`;
|
|
33
|
+
const descriptionId = description ? `${inputId}-description` : undefined;
|
|
34
|
+
const [uncontrolledHasValue, setUncontrolledHasValue] = useState(() => String(defaultValue ?? "").length > 0);
|
|
35
|
+
const hasValue = value !== undefined ? String(value).length > 0 : uncontrolledHasValue;
|
|
36
|
+
const handleChange = (event) => {
|
|
37
|
+
if (value === undefined) {
|
|
38
|
+
setUncontrolledHasValue(event.target.value.length > 0);
|
|
39
|
+
}
|
|
40
|
+
onChange?.(event);
|
|
41
|
+
};
|
|
42
|
+
const handleClear = () => {
|
|
43
|
+
const input = innerRef.current;
|
|
44
|
+
if (!input)
|
|
45
|
+
return;
|
|
46
|
+
const nativeSetter = Object.getOwnPropertyDescriptor(input.constructor.prototype, "value")?.set;
|
|
47
|
+
nativeSetter?.call(input, "");
|
|
48
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
49
|
+
input.focus();
|
|
50
|
+
if (value === undefined) {
|
|
51
|
+
setUncontrolledHasValue(false);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const handleKeyDown = (event) => {
|
|
55
|
+
if (event.key === "Escape" && hasValue) {
|
|
56
|
+
event.stopPropagation();
|
|
57
|
+
}
|
|
58
|
+
onKeyDown?.(event);
|
|
59
|
+
};
|
|
60
|
+
const fieldClassName = classNames({ "tds-field--lg": size === "lg" }, className);
|
|
61
|
+
const fieldLabelProps = ariaLabelledBy
|
|
62
|
+
? { "aria-labelledby": ariaLabelledBy }
|
|
63
|
+
: { hideLabel, label };
|
|
64
|
+
return (React__default.createElement(Field, { ...fieldLabelProps, className: fieldClassName, description: description, id: inputId },
|
|
65
|
+
React__default.createElement("div", { className: classNames("tds-search-input-control", {
|
|
66
|
+
"tds-search-input-control--has-value": hasValue,
|
|
67
|
+
}) },
|
|
68
|
+
React__default.createElement(Icon, { "aria-hidden": true, className: "tds-search-input-icon", symbol: "general#search" }),
|
|
69
|
+
React__default.createElement("input", { ...restProps, "aria-describedby": descriptionId, "aria-invalid": invalid || undefined, "aria-labelledby": ariaLabelledBy, defaultValue: defaultValue, disabled: disabled, id: inputId, onChange: handleChange, onKeyDown: handleKeyDown, readOnly: readOnly, ref: setRefs, type: "search", value: value }),
|
|
70
|
+
React__default.createElement(IconButton, { "aria-label": "Clear", icon: React__default.createElement(Icon, { "aria-hidden": true, className: "tds-search-input-clear-icon", symbol: "general#x" }), kind: "neutral-inline", onClick: handleClear, tabIndex: -1 }))));
|
|
71
|
+
});
|
|
72
|
+
SearchInput.displayName = "SearchInput";
|
|
73
|
+
|
|
74
|
+
export { SearchInput };
|
|
75
|
+
//# sourceMappingURL=SearchInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchInput.js","sources":["../../../src/components/search-input/SearchInput.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { IconButton } from \"@components/button\"\nimport { Field } from \"@components/field\"\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, {\n forwardRef,\n type InputHTMLAttributes,\n useRef,\n useState,\n} from \"react\"\n\nexport type SearchInputSize = \"lg\" | \"md\"\n\ninterface SearchInputBaseProps {\n /** Helper text below the input. Styled as an error when `invalid`. */\n description?: React.ReactNode\n /** Triggers invalid state (error border, error description, aria-invalid). */\n invalid?: boolean\n /** Visual size — cascades to the icon, input, and clear button via Field's font-size custom property. Defaults to 'md'. */\n size?: SearchInputSize\n}\n\ninterface SearchInputWithLabel extends SearchInputBaseProps {\n \"aria-labelledby\"?: never\n /** If true, the label is visually hidden but remains in the DOM/AT tree. */\n hideLabel?: boolean\n /** The visible label. */\n label: React.ReactNode\n}\n\ninterface SearchInputWithAriaLabelledBy extends SearchInputBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type SearchInputProps =\n | SearchInputWithAriaLabelledBy\n | SearchInputWithLabel\n\n/**\n * Combines standard HTML input attributes with SearchInput's own props.\n * `type` is fixed to \"search\" and not exposed; `size` is redefined above.\n */\nexport type SearchInputElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof SearchInputProps | \"size\" | \"type\"\n> &\n SearchInputProps\n\n/**\n * A search-specific input with a leading search icon and a trailing clear\n * (\"x\") button, built on `type=\"search\"`. Composes `Field` directly for\n * label, description, and state layout.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-searchinput--docs | Storybook Documentation}\n */\nexport const SearchInput = forwardRef<\n HTMLInputElement,\n SearchInputElementProps\n>(function SearchInput(\n {\n \"aria-labelledby\": ariaLabelledBy,\n className,\n defaultValue,\n description,\n disabled,\n hideLabel,\n id,\n invalid,\n label,\n onChange,\n onKeyDown,\n readOnly,\n size = \"md\",\n value,\n ...restProps\n }: SearchInputElementProps,\n ref\n) {\n const innerRef = useRef<HTMLInputElement | null>(null)\n const setRefs = (node: HTMLInputElement | null) => {\n innerRef.current = node\n if (typeof ref === \"function\") ref(node)\n else if (ref) {\n ;(ref as React.MutableRefObject<HTMLInputElement | null>).current = node\n }\n }\n\n const stableId = useId()\n const inputId = id || `tds-search-input-${stableId}`\n const descriptionId = description ? `${inputId}-description` : undefined\n\n const [uncontrolledHasValue, setUncontrolledHasValue] = useState(\n () => String(defaultValue ?? \"\").length > 0\n )\n const hasValue =\n value !== undefined ? String(value).length > 0 : uncontrolledHasValue\n\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (value === undefined) {\n setUncontrolledHasValue(event.target.value.length > 0)\n }\n onChange?.(event)\n }\n\n const handleClear = () => {\n const input = innerRef.current\n if (!input) return\n\n const nativeSetter = Object.getOwnPropertyDescriptor(\n input.constructor.prototype,\n \"value\"\n )?.set\n nativeSetter?.call(input, \"\")\n input.dispatchEvent(new Event(\"input\", { bubbles: true }))\n input.focus()\n if (value === undefined) {\n setUncontrolledHasValue(false)\n }\n }\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Escape\" && hasValue) {\n event.stopPropagation()\n }\n onKeyDown?.(event)\n }\n\n const fieldClassName = classNames(\n { \"tds-field--lg\": size === \"lg\" },\n className\n )\n\n const fieldLabelProps = ariaLabelledBy\n ? { \"aria-labelledby\": ariaLabelledBy }\n : { hideLabel, label }\n\n return (\n <Field\n {...fieldLabelProps}\n className={fieldClassName}\n description={description}\n id={inputId}\n >\n <div\n className={classNames(\"tds-search-input-control\", {\n \"tds-search-input-control--has-value\": hasValue,\n })}\n >\n <Icon\n aria-hidden\n className=\"tds-search-input-icon\"\n symbol=\"general#search\"\n />\n <input\n {...restProps}\n aria-describedby={descriptionId}\n aria-invalid={invalid || undefined}\n aria-labelledby={ariaLabelledBy}\n defaultValue={defaultValue}\n disabled={disabled}\n id={inputId}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n readOnly={readOnly}\n ref={setRefs}\n type=\"search\"\n value={value}\n />\n <IconButton\n aria-label=\"Clear\"\n icon={\n <Icon\n aria-hidden\n className=\"tds-search-input-clear-icon\"\n symbol=\"general#x\"\n />\n }\n kind=\"neutral-inline\"\n onClick={handleClear}\n tabIndex={-1}\n />\n </div>\n </Field>\n )\n})\n\nSearchInput.displayName = \"SearchInput\"\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-input/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,YAAY,EACV,uBAAuB,EACvB,gBAAgB,EAChB,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
|