@planningcenter/tapestry 3.4.1 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/button/Button.d.ts +1 -0
- package/dist/components/button/Button.d.ts.map +1 -1
- package/dist/components/button/Button.js +1 -0
- package/dist/components/button/Button.js.map +1 -1
- package/dist/components/button/DropdownButton.d.ts +1 -0
- package/dist/components/button/DropdownButton.d.ts.map +1 -1
- package/dist/components/button/DropdownButton.js +1 -0
- package/dist/components/button/DropdownButton.js.map +1 -1
- package/dist/components/button/DropdownIconButton.d.ts +1 -0
- package/dist/components/button/DropdownIconButton.d.ts.map +1 -1
- package/dist/components/button/DropdownIconButton.js +1 -0
- package/dist/components/button/DropdownIconButton.js.map +1 -1
- package/dist/components/button/IconButton.d.ts +1 -0
- package/dist/components/button/IconButton.d.ts.map +1 -1
- package/dist/components/button/IconButton.js +1 -0
- package/dist/components/button/IconButton.js.map +1 -1
- package/dist/components/checkbox/Checkbox.d.ts +1 -0
- package/dist/components/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/checkbox/Checkbox.js +1 -0
- package/dist/components/checkbox/Checkbox.js.map +1 -1
- package/dist/components/combo-box/ComboBox.d.ts +1 -1
- package/dist/components/combo-box/ComboBox.d.ts.map +1 -1
- package/dist/components/combo-box/ComboBox.js.map +1 -1
- package/dist/components/date-picker/DatePicker.d.ts +2 -1
- package/dist/components/date-picker/DatePicker.d.ts.map +1 -1
- package/dist/components/date-picker/DatePicker.js +1 -0
- package/dist/components/date-picker/DatePicker.js.map +1 -1
- package/dist/components/dropdown/Dropdown.d.ts +1 -0
- package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
- package/dist/components/dropdown/Dropdown.js +1 -0
- package/dist/components/dropdown/Dropdown.js.map +1 -1
- package/dist/components/field/Field.d.ts +43 -0
- package/dist/components/field/Field.d.ts.map +1 -0
- package/dist/components/field/Field.js +38 -0
- package/dist/components/field/Field.js.map +1 -0
- package/dist/components/field/index.d.ts +4 -0
- package/dist/components/field/index.d.ts.map +1 -0
- package/dist/components/flex/Flex.d.ts +69 -0
- package/dist/components/flex/Flex.d.ts.map +1 -0
- package/dist/components/flex/Flex.js +18 -0
- package/dist/components/flex/Flex.js.map +1 -0
- package/dist/components/flex/index.d.ts +3 -0
- package/dist/components/flex/index.d.ts.map +1 -0
- package/dist/components/input/Input.d.ts +1 -0
- package/dist/components/input/Input.d.ts.map +1 -1
- package/dist/components/input/Input.js +1 -0
- package/dist/components/input/Input.js.map +1 -1
- package/dist/components/link/Link.d.ts +1 -0
- package/dist/components/link/Link.d.ts.map +1 -1
- package/dist/components/link/Link.js +1 -0
- package/dist/components/link/Link.js.map +1 -1
- package/dist/components/number-stepper/NumberStepper.d.ts +1 -1
- package/dist/components/number-stepper/NumberStepper.d.ts.map +1 -1
- package/dist/components/number-stepper/NumberStepper.js.map +1 -1
- package/dist/components/radio/Radio.d.ts +1 -0
- package/dist/components/radio/Radio.d.ts.map +1 -1
- package/dist/components/radio/Radio.js +1 -0
- package/dist/components/radio/Radio.js.map +1 -1
- package/dist/components/select/Select.d.ts +1 -0
- package/dist/components/select/Select.d.ts.map +1 -1
- package/dist/components/select/Select.js +1 -0
- package/dist/components/select/Select.js.map +1 -1
- package/dist/components/select/SelectNative.js +1 -1
- package/dist/components/select/SelectNative.js.map +1 -1
- package/dist/components/select/SelectPopover.js +1 -1
- package/dist/components/select/SelectPopover.js.map +1 -1
- package/dist/components/text-area/TextArea.d.ts +1 -0
- package/dist/components/text-area/TextArea.d.ts.map +1 -1
- package/dist/components/text-area/TextArea.js +1 -0
- package/dist/components/text-area/TextArea.js.map +1 -1
- package/dist/components/time-field/TimeField.d.ts +2 -1
- package/dist/components/time-field/TimeField.d.ts.map +1 -1
- package/dist/components/time-field/TimeField.js +1 -0
- package/dist/components/time-field/TimeField.js.map +1 -1
- package/dist/components/toggle-switch/ToggleSwitch.d.ts +1 -0
- package/dist/components/toggle-switch/ToggleSwitch.d.ts.map +1 -1
- package/dist/components/toggle-switch/ToggleSwitch.js +1 -0
- package/dist/components/toggle-switch/ToggleSwitch.js.map +1 -1
- package/dist/index.css +351 -154
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/reactRender.css +2266 -1426
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +2266 -1426
- package/dist/reactRenderLegacy.css.map +1 -1
- package/dist/unstable.css +1114 -274
- package/dist/unstable.css.map +1 -1
- package/dist/unstable.d.ts +1 -1
- package/dist/unstable.d.ts.map +1 -1
- package/dist/unstable.js +3 -1
- package/dist/unstable.js.map +1 -1
- package/dist/utilities/breakpoints.d.ts +9 -0
- package/dist/utilities/breakpoints.d.ts.map +1 -0
- package/dist/utilities/spacingTokens.d.ts +2 -0
- package/dist/utilities/spacingTokens.d.ts.map +1 -0
- package/package.json +8 -6
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
interface FieldBaseProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
className?: string;
|
|
5
|
+
description?: ReactNode;
|
|
6
|
+
id: string;
|
|
7
|
+
}
|
|
8
|
+
interface FieldLabeledProps extends FieldBaseProps {
|
|
9
|
+
"aria-labelledby"?: never;
|
|
10
|
+
hideLabel?: boolean;
|
|
11
|
+
label: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
interface FieldExternallyLabeledProps extends FieldBaseProps {
|
|
14
|
+
"aria-labelledby": string;
|
|
15
|
+
hideLabel?: never;
|
|
16
|
+
label?: never;
|
|
17
|
+
}
|
|
18
|
+
export type FieldProps = FieldExternallyLabeledProps | FieldLabeledProps;
|
|
19
|
+
/**
|
|
20
|
+
* A layout primitive that wraps a single form control with a label,
|
|
21
|
+
* optional description, and state-driven styling (required, invalid, disabled).
|
|
22
|
+
*
|
|
23
|
+
* **Reach for a Tapestry form component first** — `Input`, `Checkbox`, `Radio`,
|
|
24
|
+
* `ToggleSwitch`, `Select`, `ComboBox`, `DatePicker`, `TimeField`. Those
|
|
25
|
+
* components handle their own label / description / state styling internally.
|
|
26
|
+
*
|
|
27
|
+
* **Use `Field` directly only when no Tapestry component fits your control** —
|
|
28
|
+
* a custom widget, a third-party input, or an in-progress design.
|
|
29
|
+
*
|
|
30
|
+
* **Wiring contract** — Field renders children completely untouched. The caller
|
|
31
|
+
* is responsible for:
|
|
32
|
+
* - Setting `id` on the control to match the `id` prop passed to Field.
|
|
33
|
+
* - Setting `aria-describedby="{id}-description"` on the control when
|
|
34
|
+
* `description` is provided.
|
|
35
|
+
* - Setting `aria-labelledby` on the control when using `aria-labelledby` mode.
|
|
36
|
+
* - Setting state attributes (`required`, `disabled`, `aria-invalid`) directly
|
|
37
|
+
* on the control — Field's CSS detects them via `:has()`.
|
|
38
|
+
*
|
|
39
|
+
* @component
|
|
40
|
+
*/
|
|
41
|
+
export declare function Field({ "aria-labelledby": ariaLabelledBy, children, className, description, hideLabel, id, label, }: FieldProps): React.JSX.Element;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=Field.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../../src/components/field/Field.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAExC,UAAU,cAAc;IACtB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,EAAE,EAAE,MAAM,CAAA;CACX;AAED,UAAU,iBAAkB,SAAQ,cAAc;IAChD,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,2BAA4B,SAAQ,cAAc;IAC1D,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAAG,2BAA2B,GAAG,iBAAiB,CAAA;AAExE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,KAAK,CAAC,EACpB,iBAAiB,EAAE,cAAc,EACjC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,SAAS,EACT,EAAE,EACF,KAAK,GACN,EAAE,UAAU,qBA6BZ"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Icon from '../../utilities/Icon.js';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A layout primitive that wraps a single form control with a label,
|
|
7
|
+
* optional description, and state-driven styling (required, invalid, disabled).
|
|
8
|
+
*
|
|
9
|
+
* **Reach for a Tapestry form component first** — `Input`, `Checkbox`, `Radio`,
|
|
10
|
+
* `ToggleSwitch`, `Select`, `ComboBox`, `DatePicker`, `TimeField`. Those
|
|
11
|
+
* components handle their own label / description / state styling internally.
|
|
12
|
+
*
|
|
13
|
+
* **Use `Field` directly only when no Tapestry component fits your control** —
|
|
14
|
+
* a custom widget, a third-party input, or an in-progress design.
|
|
15
|
+
*
|
|
16
|
+
* **Wiring contract** — Field renders children completely untouched. The caller
|
|
17
|
+
* is responsible for:
|
|
18
|
+
* - Setting `id` on the control to match the `id` prop passed to Field.
|
|
19
|
+
* - Setting `aria-describedby="{id}-description"` on the control when
|
|
20
|
+
* `description` is provided.
|
|
21
|
+
* - Setting `aria-labelledby` on the control when using `aria-labelledby` mode.
|
|
22
|
+
* - Setting state attributes (`required`, `disabled`, `aria-invalid`) directly
|
|
23
|
+
* on the control — Field's CSS detects them via `:has()`.
|
|
24
|
+
*
|
|
25
|
+
* @component
|
|
26
|
+
*/
|
|
27
|
+
function Field({ "aria-labelledby": ariaLabelledBy, children, className, description, hideLabel, id, label, }) {
|
|
28
|
+
const descriptionId = `${id}-description`;
|
|
29
|
+
return (React__default.createElement("div", { className: classNames("tds-field", className) },
|
|
30
|
+
label && !ariaLabelledBy && (React__default.createElement("label", { className: classNames("tds-field-label", hideLabel && "tds-field-label--hidden"), htmlFor: id }, label)),
|
|
31
|
+
children,
|
|
32
|
+
description && (React__default.createElement("p", { className: "tds-field-description", id: descriptionId },
|
|
33
|
+
React__default.createElement(Icon, { "aria-hidden": true, className: "tds-field-description-invalid-icon", symbol: "general#exclamation-triangle" }),
|
|
34
|
+
description))));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { Field };
|
|
38
|
+
//# sourceMappingURL=Field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Field.js","sources":["../../../src/components/field/Field.tsx"],"sourcesContent":["import Icon from \"@utilities/Icon\"\nimport classNames from \"classnames\"\nimport React, { ReactNode } from \"react\"\n\ninterface FieldBaseProps {\n children: ReactNode\n className?: string\n description?: ReactNode\n id: string\n}\n\ninterface FieldLabeledProps extends FieldBaseProps {\n \"aria-labelledby\"?: never\n hideLabel?: boolean\n label: ReactNode\n}\n\ninterface FieldExternallyLabeledProps extends FieldBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type FieldProps = FieldExternallyLabeledProps | FieldLabeledProps\n\n/**\n * A layout primitive that wraps a single form control with a label,\n * optional description, and state-driven styling (required, invalid, disabled).\n *\n * **Reach for a Tapestry form component first** — `Input`, `Checkbox`, `Radio`,\n * `ToggleSwitch`, `Select`, `ComboBox`, `DatePicker`, `TimeField`. Those\n * components handle their own label / description / state styling internally.\n *\n * **Use `Field` directly only when no Tapestry component fits your control** —\n * a custom widget, a third-party input, or an in-progress design.\n *\n * **Wiring contract** — Field renders children completely untouched. The caller\n * is responsible for:\n * - Setting `id` on the control to match the `id` prop passed to Field.\n * - Setting `aria-describedby=\"{id}-description\"` on the control when\n * `description` is provided.\n * - Setting `aria-labelledby` on the control when using `aria-labelledby` mode.\n * - Setting state attributes (`required`, `disabled`, `aria-invalid`) directly\n * on the control — Field's CSS detects them via `:has()`.\n *\n * @component\n */\nexport function Field({\n \"aria-labelledby\": ariaLabelledBy,\n children,\n className,\n description,\n hideLabel,\n id,\n label,\n}: FieldProps) {\n const descriptionId = `${id}-description`\n\n return (\n <div className={classNames(\"tds-field\", className)}>\n {label && !ariaLabelledBy && (\n <label\n className={classNames(\n \"tds-field-label\",\n hideLabel && \"tds-field-label--hidden\"\n )}\n htmlFor={id}\n >\n {label}\n </label>\n )}\n {children}\n {description && (\n <p className=\"tds-field-description\" id={descriptionId}>\n <Icon\n aria-hidden\n className=\"tds-field-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {description}\n </p>\n )}\n </div>\n )\n}\n"],"names":["React"],"mappings":";;;;AAyBA;;;;;;;;;;;;;;;;;;;;;AAqBG;SACa,KAAK,CAAC,EACpB,iBAAiB,EAAE,cAAc,EACjC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,SAAS,EACT,EAAE,EACF,KAAK,GACM,EAAA;AACX,IAAA,MAAM,aAAa,GAAG,CAAA,EAAG,EAAE,cAAc;IAEzC,QACEA,sCAAK,SAAS,EAAE,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,EAAA;QAC/C,KAAK,IAAI,CAAC,cAAc,KACvBA,cAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EACE,SAAS,EAAE,UAAU,CACnB,iBAAiB,EACjB,SAAS,IAAI,yBAAyB,CACvC,EACD,OAAO,EAAE,EAAE,EAAA,EAEV,KAAK,CACA,CACT;QACA,QAAQ;QACR,WAAW,KACVA,cAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAG,SAAS,EAAC,uBAAuB,EAAC,EAAE,EAAE,aAAa,EAAA;YACpDA,cAAA,CAAA,aAAA,CAAC,IAAI,yBAEH,SAAS,EAAC,oCAAoC,EAC9C,MAAM,EAAC,8BAA8B,EAAA,CACrC;AACD,YAAA,WAAW,CACV,CACL,CACG;AAEV;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/field/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAEpB,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import "../../css/layout.css";
|
|
2
|
+
import { type Breakpoint } from "../../utilities/breakpoints";
|
|
3
|
+
import { type Spacing } from "../../utilities/spacingTokens";
|
|
4
|
+
import React from "react";
|
|
5
|
+
interface FlexSizingExpand {
|
|
6
|
+
basis?: never;
|
|
7
|
+
/** A convenience prop that sets `flex: 1 1 0%; min-width: 0` to fill remaining space. Mutually exclusive with `grow`, `shrink`, and `basis`. */
|
|
8
|
+
expand?: true;
|
|
9
|
+
grow?: never;
|
|
10
|
+
shrink?: never;
|
|
11
|
+
}
|
|
12
|
+
interface FlexSizing {
|
|
13
|
+
/** The initial main size of this flex item before space is distributed. */
|
|
14
|
+
basis?: 0 | "auto" | "100%";
|
|
15
|
+
expand?: never;
|
|
16
|
+
/** The flex grow factor of this flex item. */
|
|
17
|
+
grow?: 0 | 1;
|
|
18
|
+
/** The flex shrink factor of this flex item. */
|
|
19
|
+
shrink?: 0 | 1;
|
|
20
|
+
}
|
|
21
|
+
export type FlexResponsive = Partial<Record<Breakpoint, Omit<FlexBaseProps, "as" | "expand" | "inline" | "responsive">>>;
|
|
22
|
+
export type FlexElement = "article" | "aside" | "dd" | "div" | "dl" | "dt" | "footer" | "header" | "li" | "main" | "nav" | "ol" | "section" | "ul";
|
|
23
|
+
type FlexBaseProps = {
|
|
24
|
+
/** The alignment of children along the cross axis. */
|
|
25
|
+
align?: "start" | "center" | "end" | "stretch" | "baseline";
|
|
26
|
+
/** The alignment of this flex item along the cross axis, overriding the container's `align`. */
|
|
27
|
+
alignSelf?: "auto" | "start" | "center" | "end" | "stretch" | "baseline";
|
|
28
|
+
/** The HTML element to render. */
|
|
29
|
+
as?: FlexElement;
|
|
30
|
+
/** The column gap between children. Overrides `gap` on the column axis. Tapestry spacing scale. */
|
|
31
|
+
columnGap?: Spacing;
|
|
32
|
+
/** The direction of the main axis. */
|
|
33
|
+
direction?: "row" | "row-reverse" | "column" | "column-reverse";
|
|
34
|
+
/** The gap between children. Tapestry spacing scale. */
|
|
35
|
+
gap?: Spacing;
|
|
36
|
+
/** If set, renders as `inline-flex` instead of `flex`. */
|
|
37
|
+
inline?: true;
|
|
38
|
+
/** The distribution of space between and around children along the main axis. */
|
|
39
|
+
justify?: "start" | "center" | "end" | "space-between" | "space-around" | "space-evenly";
|
|
40
|
+
/** The padding on all sides. Tapestry spacing scale. */
|
|
41
|
+
padding?: Spacing;
|
|
42
|
+
/** The padding on the block axis. Overrides `padding` on the block axis. Tapestry spacing scale. */
|
|
43
|
+
paddingBlock?: Spacing;
|
|
44
|
+
/** The padding on the inline axis. Overrides `padding` on the inline axis. Tapestry spacing scale. */
|
|
45
|
+
paddingInline?: Spacing;
|
|
46
|
+
/**
|
|
47
|
+
* Responsive overrides. Mobile-first with breakpoints as keys.
|
|
48
|
+
* @example { md: { direction: "row", gap: 2 } }
|
|
49
|
+
*/
|
|
50
|
+
responsive?: FlexResponsive;
|
|
51
|
+
/** The row gap between children. Overrides `gap` on the row axis. Tapestry spacing scale. */
|
|
52
|
+
rowGap?: Spacing;
|
|
53
|
+
/** Whether children are forced onto one line or can wrap onto multiple lines. */
|
|
54
|
+
wrap?: "nowrap" | "wrap" | "wrap-reverse";
|
|
55
|
+
} & (FlexSizingExpand | FlexSizing);
|
|
56
|
+
export type FlexProps = FlexBaseProps & Omit<React.HTMLAttributes<HTMLElement>, keyof FlexBaseProps>;
|
|
57
|
+
interface FlexComponent {
|
|
58
|
+
(props: FlexProps & React.RefAttributes<HTMLElement>): React.ReactElement | null;
|
|
59
|
+
displayName?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A flexbox layout primitive with token-constrained spacing.
|
|
63
|
+
*
|
|
64
|
+
* @component
|
|
65
|
+
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-flex--docs | Storybook Documentation}
|
|
66
|
+
*/
|
|
67
|
+
export declare const Flex: FlexComponent;
|
|
68
|
+
export {};
|
|
69
|
+
//# sourceMappingURL=Flex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Flex.d.ts","sourceRoot":"","sources":["../../../src/components/flex/Flex.tsx"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAA;AAE7B,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAEvD,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,gJAAgJ;IAChJ,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,MAAM,CAAC,EAAE,KAAK,CAAA;CACf;AAED,UAAU,UAAU;IAClB,2EAA2E;IAC3E,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,CAAA;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,8CAA8C;IAC9C,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACZ,gDAAgD;IAChD,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;CACf;AAED,MAAM,MAAM,cAAc,GAAG,OAAO,CAClC,MAAM,CACJ,UAAU,EACV,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC,CAC/D,CACF,CAAA;AAED,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,OAAO,GACP,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,QAAQ,GACR,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,KAAK,GACL,IAAI,GACJ,SAAS,GACT,IAAI,CAAA;AAER,KAAK,aAAa,GAAG;IACnB,sDAAsD;IACtD,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAA;IAC3D,gGAAgG;IAChG,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAA;IACxE,kCAAkC;IAClC,EAAE,CAAC,EAAE,WAAW,CAAA;IAChB,mGAAmG;IACnG,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,sCAAsC;IACtC,SAAS,CAAC,EAAE,KAAK,GAAG,aAAa,GAAG,QAAQ,GAAG,gBAAgB,CAAA;IAC/D,wDAAwD;IACxD,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,iFAAiF;IACjF,OAAO,CAAC,EACJ,OAAO,GACP,QAAQ,GACR,KAAK,GACL,eAAe,GACf,cAAc,GACd,cAAc,CAAA;IAClB,wDAAwD;IACxD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oGAAoG;IACpG,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,sGAAsG;IACtG,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,cAAc,CAAA;IAC3B,6FAA6F;IAC7F,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,iFAAiF;IACjF,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,cAAc,CAAA;CAC1C,GAAG,CAAC,gBAAgB,GAAG,UAAU,CAAC,CAAA;AAEnC,MAAM,MAAM,SAAS,GAAG,aAAa,GACnC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,aAAa,CAAC,CAAA;AAE9D,UAAU,aAAa;IACrB,CACE,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,GAClD,KAAK,CAAC,YAAY,GAAG,IAAI,CAAA;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAgIA,aAAa,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React__default, { forwardRef } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A flexbox layout primitive with token-constrained spacing.
|
|
6
|
+
*
|
|
7
|
+
* @component
|
|
8
|
+
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-flex--docs | Storybook Documentation}
|
|
9
|
+
*/
|
|
10
|
+
const Flex = forwardRef(function Flex({ align, alignSelf, as: Element = "div", basis, className, columnGap, direction, expand, gap, grow, inline, justify, padding, paddingBlock, paddingInline, responsive, rowGap, shrink, wrap, ...rest }, ref) {
|
|
11
|
+
const { xs, sm, md, lg, xl } = responsive ?? {};
|
|
12
|
+
const Tag = Element;
|
|
13
|
+
return (React__default.createElement(Tag, { ...rest, className: classNames("tds-flex", className), ref: ref, "data-flex-align": align, "data-flex-align-self": alignSelf, "data-flex-basis": basis, "data-flex-direction": direction, "data-flex-expand": expand || undefined, "data-flex-gap": gap, "data-flex-row-gap": rowGap, "data-flex-column-gap": columnGap, "data-flex-grow": grow, "data-flex-inline": inline || undefined, "data-flex-justify": justify, "data-flex-shrink": shrink, "data-flex-wrap": wrap, "data-padding": padding, "data-padding-block": paddingBlock, "data-padding-inline": paddingInline, "data-flex-align-xs": xs?.align, "data-flex-align-self-xs": xs?.alignSelf, "data-flex-basis-xs": xs?.basis, "data-flex-direction-xs": xs?.direction, "data-flex-gap-xs": xs?.gap, "data-flex-row-gap-xs": xs?.rowGap, "data-flex-column-gap-xs": xs?.columnGap, "data-flex-grow-xs": xs?.grow, "data-flex-justify-xs": xs?.justify, "data-flex-shrink-xs": xs?.shrink, "data-flex-wrap-xs": xs?.wrap, "data-padding-xs": xs?.padding, "data-padding-block-xs": xs?.paddingBlock, "data-padding-inline-xs": xs?.paddingInline, "data-flex-align-sm": sm?.align, "data-flex-align-self-sm": sm?.alignSelf, "data-flex-basis-sm": sm?.basis, "data-flex-direction-sm": sm?.direction, "data-flex-gap-sm": sm?.gap, "data-flex-row-gap-sm": sm?.rowGap, "data-flex-column-gap-sm": sm?.columnGap, "data-flex-grow-sm": sm?.grow, "data-flex-justify-sm": sm?.justify, "data-flex-shrink-sm": sm?.shrink, "data-flex-wrap-sm": sm?.wrap, "data-padding-sm": sm?.padding, "data-padding-block-sm": sm?.paddingBlock, "data-padding-inline-sm": sm?.paddingInline, "data-flex-align-md": md?.align, "data-flex-align-self-md": md?.alignSelf, "data-flex-basis-md": md?.basis, "data-flex-direction-md": md?.direction, "data-flex-gap-md": md?.gap, "data-flex-row-gap-md": md?.rowGap, "data-flex-column-gap-md": md?.columnGap, "data-flex-grow-md": md?.grow, "data-flex-justify-md": md?.justify, "data-flex-shrink-md": md?.shrink, "data-flex-wrap-md": md?.wrap, "data-padding-md": md?.padding, "data-padding-block-md": md?.paddingBlock, "data-padding-inline-md": md?.paddingInline, "data-flex-align-lg": lg?.align, "data-flex-align-self-lg": lg?.alignSelf, "data-flex-basis-lg": lg?.basis, "data-flex-direction-lg": lg?.direction, "data-flex-gap-lg": lg?.gap, "data-flex-row-gap-lg": lg?.rowGap, "data-flex-column-gap-lg": lg?.columnGap, "data-flex-grow-lg": lg?.grow, "data-flex-justify-lg": lg?.justify, "data-flex-shrink-lg": lg?.shrink, "data-flex-wrap-lg": lg?.wrap, "data-padding-lg": lg?.padding, "data-padding-block-lg": lg?.paddingBlock, "data-padding-inline-lg": lg?.paddingInline, "data-flex-align-xl": xl?.align, "data-flex-align-self-xl": xl?.alignSelf, "data-flex-basis-xl": xl?.basis, "data-flex-direction-xl": xl?.direction, "data-flex-gap-xl": xl?.gap, "data-flex-row-gap-xl": xl?.rowGap, "data-flex-column-gap-xl": xl?.columnGap, "data-flex-grow-xl": xl?.grow, "data-flex-justify-xl": xl?.justify, "data-flex-shrink-xl": xl?.shrink, "data-flex-wrap-xl": xl?.wrap, "data-padding-xl": xl?.padding, "data-padding-block-xl": xl?.paddingBlock, "data-padding-inline-xl": xl?.paddingInline }));
|
|
14
|
+
});
|
|
15
|
+
Flex.displayName = "Flex";
|
|
16
|
+
|
|
17
|
+
export { Flex };
|
|
18
|
+
//# sourceMappingURL=Flex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Flex.js","sources":["../../../src/components/flex/Flex.tsx"],"sourcesContent":["import \"../../css/layout.css\"\n\nimport { type Breakpoint } from \"@utilities/breakpoints\"\nimport { type Spacing } from \"@utilities/spacingTokens\"\nimport classNames from \"classnames\"\nimport React, { forwardRef } from \"react\"\n\ninterface FlexSizingExpand {\n basis?: never\n /** A convenience prop that sets `flex: 1 1 0%; min-width: 0` to fill remaining space. Mutually exclusive with `grow`, `shrink`, and `basis`. */\n expand?: true\n grow?: never\n shrink?: never\n}\n\ninterface FlexSizing {\n /** The initial main size of this flex item before space is distributed. */\n basis?: 0 | \"auto\" | \"100%\"\n expand?: never\n /** The flex grow factor of this flex item. */\n grow?: 0 | 1\n /** The flex shrink factor of this flex item. */\n shrink?: 0 | 1\n}\n\nexport type FlexResponsive = Partial<\n Record<\n Breakpoint,\n Omit<FlexBaseProps, \"as\" | \"expand\" | \"inline\" | \"responsive\">\n >\n>\n\nexport type FlexElement =\n | \"article\"\n | \"aside\"\n | \"dd\"\n | \"div\"\n | \"dl\"\n | \"dt\"\n | \"footer\"\n | \"header\"\n | \"li\"\n | \"main\"\n | \"nav\"\n | \"ol\"\n | \"section\"\n | \"ul\"\n\ntype FlexBaseProps = {\n /** The alignment of children along the cross axis. */\n align?: \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\"\n /** The alignment of this flex item along the cross axis, overriding the container's `align`. */\n alignSelf?: \"auto\" | \"start\" | \"center\" | \"end\" | \"stretch\" | \"baseline\"\n /** The HTML element to render. */\n as?: FlexElement\n /** The column gap between children. Overrides `gap` on the column axis. Tapestry spacing scale. */\n columnGap?: Spacing\n /** The direction of the main axis. */\n direction?: \"row\" | \"row-reverse\" | \"column\" | \"column-reverse\"\n /** The gap between children. Tapestry spacing scale. */\n gap?: Spacing\n /** If set, renders as `inline-flex` instead of `flex`. */\n inline?: true\n /** The distribution of space between and around children along the main axis. */\n justify?:\n | \"start\"\n | \"center\"\n | \"end\"\n | \"space-between\"\n | \"space-around\"\n | \"space-evenly\"\n /** The padding on all sides. Tapestry spacing scale. */\n padding?: Spacing\n /** The padding on the block axis. Overrides `padding` on the block axis. Tapestry spacing scale. */\n paddingBlock?: Spacing\n /** The padding on the inline axis. Overrides `padding` on the inline axis. Tapestry spacing scale. */\n paddingInline?: Spacing\n /**\n * Responsive overrides. Mobile-first with breakpoints as keys.\n * @example { md: { direction: \"row\", gap: 2 } }\n */\n responsive?: FlexResponsive\n /** The row gap between children. Overrides `gap` on the row axis. Tapestry spacing scale. */\n rowGap?: Spacing\n /** Whether children are forced onto one line or can wrap onto multiple lines. */\n wrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\"\n} & (FlexSizingExpand | FlexSizing)\n\nexport type FlexProps = FlexBaseProps &\n Omit<React.HTMLAttributes<HTMLElement>, keyof FlexBaseProps>\n\ninterface FlexComponent {\n (\n props: FlexProps & React.RefAttributes<HTMLElement>\n ): React.ReactElement | null\n displayName?: string\n}\n\n/**\n * A flexbox layout primitive with token-constrained spacing.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-flex--docs | Storybook Documentation}\n */\nexport const Flex = forwardRef(function Flex(\n {\n align,\n alignSelf,\n as: Element = \"div\",\n basis,\n className,\n columnGap,\n direction,\n expand,\n gap,\n grow,\n inline,\n justify,\n padding,\n paddingBlock,\n paddingInline,\n responsive,\n rowGap,\n shrink,\n wrap,\n ...rest\n }: FlexProps,\n ref: React.ForwardedRef<HTMLElement>\n) {\n const { xs, sm, md, lg, xl } = responsive ?? {}\n\n const Tag = Element as unknown as React.ComponentType<\n React.HTMLAttributes<HTMLElement> & React.RefAttributes<HTMLElement>\n >\n return (\n <Tag\n {...rest}\n className={classNames(\"tds-flex\", className)}\n ref={ref}\n data-flex-align={align}\n data-flex-align-self={alignSelf}\n data-flex-basis={basis}\n data-flex-direction={direction}\n data-flex-expand={expand || undefined}\n data-flex-gap={gap}\n data-flex-row-gap={rowGap}\n data-flex-column-gap={columnGap}\n data-flex-grow={grow}\n data-flex-inline={inline || undefined}\n data-flex-justify={justify}\n data-flex-shrink={shrink}\n data-flex-wrap={wrap}\n data-padding={padding}\n data-padding-block={paddingBlock}\n data-padding-inline={paddingInline}\n /* Breakpoint xs */\n data-flex-align-xs={xs?.align}\n data-flex-align-self-xs={xs?.alignSelf}\n data-flex-basis-xs={xs?.basis}\n data-flex-direction-xs={xs?.direction}\n data-flex-gap-xs={xs?.gap}\n data-flex-row-gap-xs={xs?.rowGap}\n data-flex-column-gap-xs={xs?.columnGap}\n data-flex-grow-xs={xs?.grow}\n data-flex-justify-xs={xs?.justify}\n data-flex-shrink-xs={xs?.shrink}\n data-flex-wrap-xs={xs?.wrap}\n data-padding-xs={xs?.padding}\n data-padding-block-xs={xs?.paddingBlock}\n data-padding-inline-xs={xs?.paddingInline}\n /* Breakpoint sm */\n data-flex-align-sm={sm?.align}\n data-flex-align-self-sm={sm?.alignSelf}\n data-flex-basis-sm={sm?.basis}\n data-flex-direction-sm={sm?.direction}\n data-flex-gap-sm={sm?.gap}\n data-flex-row-gap-sm={sm?.rowGap}\n data-flex-column-gap-sm={sm?.columnGap}\n data-flex-grow-sm={sm?.grow}\n data-flex-justify-sm={sm?.justify}\n data-flex-shrink-sm={sm?.shrink}\n data-flex-wrap-sm={sm?.wrap}\n data-padding-sm={sm?.padding}\n data-padding-block-sm={sm?.paddingBlock}\n data-padding-inline-sm={sm?.paddingInline}\n /* Breakpoint md */\n data-flex-align-md={md?.align}\n data-flex-align-self-md={md?.alignSelf}\n data-flex-basis-md={md?.basis}\n data-flex-direction-md={md?.direction}\n data-flex-gap-md={md?.gap}\n data-flex-row-gap-md={md?.rowGap}\n data-flex-column-gap-md={md?.columnGap}\n data-flex-grow-md={md?.grow}\n data-flex-justify-md={md?.justify}\n data-flex-shrink-md={md?.shrink}\n data-flex-wrap-md={md?.wrap}\n data-padding-md={md?.padding}\n data-padding-block-md={md?.paddingBlock}\n data-padding-inline-md={md?.paddingInline}\n /* Breakpoint lg */\n data-flex-align-lg={lg?.align}\n data-flex-align-self-lg={lg?.alignSelf}\n data-flex-basis-lg={lg?.basis}\n data-flex-direction-lg={lg?.direction}\n data-flex-gap-lg={lg?.gap}\n data-flex-row-gap-lg={lg?.rowGap}\n data-flex-column-gap-lg={lg?.columnGap}\n data-flex-grow-lg={lg?.grow}\n data-flex-justify-lg={lg?.justify}\n data-flex-shrink-lg={lg?.shrink}\n data-flex-wrap-lg={lg?.wrap}\n data-padding-lg={lg?.padding}\n data-padding-block-lg={lg?.paddingBlock}\n data-padding-inline-lg={lg?.paddingInline}\n /* Breakpoint xl */\n data-flex-align-xl={xl?.align}\n data-flex-align-self-xl={xl?.alignSelf}\n data-flex-basis-xl={xl?.basis}\n data-flex-direction-xl={xl?.direction}\n data-flex-gap-xl={xl?.gap}\n data-flex-row-gap-xl={xl?.rowGap}\n data-flex-column-gap-xl={xl?.columnGap}\n data-flex-grow-xl={xl?.grow}\n data-flex-justify-xl={xl?.justify}\n data-flex-shrink-xl={xl?.shrink}\n data-flex-wrap-xl={xl?.wrap}\n data-padding-xl={xl?.padding}\n data-padding-block-xl={xl?.paddingBlock}\n data-padding-inline-xl={xl?.paddingInline}\n />\n )\n}) as unknown as FlexComponent\n\nFlex.displayName = \"Flex\"\n"],"names":["React"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/flex/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AACpE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA"}
|
|
@@ -47,6 +47,7 @@ export type InputElementProps = Omit<InputHTMLAttributes<HTMLInputElement>, keyo
|
|
|
47
47
|
*
|
|
48
48
|
* @component
|
|
49
49
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}
|
|
50
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
50
51
|
*/
|
|
51
52
|
export declare const Input: React.ForwardRefExoticComponent<InputElementProps & React.RefAttributes<HTMLInputElement>>;
|
|
52
53
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,KAAK,CAAA;AAET,UAAU,cAAc;IACtB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,qBAAsB,SAAQ,cAAc;IACpD,mEAAmE;IACnE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,cAAc;IACnD,mEAAmE;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CACnC,GACC,UAAU,CAAA;AAEZ
|
|
1
|
+
{"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAEnE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,MAAM,GACN,KAAK,CAAA;AAET,UAAU,cAAc;IACtB,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gFAAgF;IAChF,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gDAAgD;IAChD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,qBAAsB,SAAQ,cAAc;IACpD,mEAAmE;IACnE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,oBAAqB,SAAQ,cAAc;IACnD,mEAAmE;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,oBAAoB,GACpB,qBAAqB,CAAA;AAEzB;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CACnC,GACC,UAAU,CAAA;AAEZ;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,4FA2EjB,CAAA"}
|
|
@@ -10,6 +10,7 @@ import React__default, { forwardRef } from 'react';
|
|
|
10
10
|
*
|
|
11
11
|
* @component
|
|
12
12
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}
|
|
13
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
13
14
|
*/
|
|
14
15
|
const Input = forwardRef(function Input({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, autoComplete, autoWidth, className, description, hideLabel, id, invalid, label, onFocus, selectTextOnFocus, size = "md", type = "text", ...restProps }, ref) {
|
|
15
16
|
const autoCompleteBlockingProps = autoComplete === "off"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Input.js","sources":["../../../src/components/input/Input.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { InputTextBase } from \"@components/input-text-base\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type InputHTMLAttributes } from \"react\"\n\nexport type InputSize = \"lg\" | \"md\"\n\nexport type InputType =\n | \"email\"\n | \"number\"\n | \"password\"\n | \"search\"\n | \"tel\"\n | \"text\"\n | \"url\"\n\ninterface InputBaseProps {\n /** If true, the input width grows to fit content. */\n autoWidth?: boolean\n /** Helper text displayed below the input. Styled as an error when `invalid`. */\n description?: string\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** If true, all text is selected when the input receives focus. */\n selectTextOnFocus?: boolean\n /** The size of the input. */\n size?: InputSize\n /** Supported input types — defaults to 'text' */\n type?: InputType\n}\n\ninterface InputWithVisibleLabel extends InputBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel?: false\n /** The label text for the input. */\n label: React.ReactNode\n}\n\ninterface InputWithHiddenLabel extends InputBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel: true\n /** The label text for the input. Must be a string when hidden. */\n label: string\n}\n\ninterface InputWithAriaLabelledBy extends InputBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type InputProps =\n | InputWithAriaLabelledBy\n | InputWithHiddenLabel\n | InputWithVisibleLabel\n\n/**\n * Combines standard HTML input attributes with custom Input props.\n * Omits 'size' and 'type' from HTML attributes to avoid conflict with our strict types.\n */\nexport type InputElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof InputProps | \"size\" | \"type\"\n> &\n InputProps\n\n/**\n * A text input component that renders as an HTML `<input>` with a label and\n * optional description. Supports the standard text-like input types\n * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`), invalid\n * state, and `lg`/`md` sizing.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}\n */\nexport const Input = forwardRef<HTMLInputElement, InputElementProps>(\n function Input(\n {\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n autoComplete,\n autoWidth,\n className,\n description,\n hideLabel,\n id,\n invalid,\n label,\n onFocus,\n selectTextOnFocus,\n size = \"md\",\n type = \"text\",\n ...restProps\n }: InputElementProps,\n ref\n ) {\n const autoCompleteBlockingProps =\n autoComplete === \"off\"\n ? {\n \"data-1p-ignore\": true,\n \"data-bwignore\": true,\n \"data-form-type\": \"other\",\n \"data-lpignore\": true,\n }\n : {}\n\n const handleFocus = selectTextOnFocus\n ? (event: React.FocusEvent<HTMLInputElement>) => {\n try {\n event.currentTarget.select()\n } catch {\n // Some input types (e.g. number) do not support text selection.\n }\n onFocus?.(event)\n }\n : onFocus\n\n const wrapperClassName = classNames(\n { \"tds-input--auto-width\": autoWidth },\n className\n )\n\n return (\n <InputTextBase\n className={wrapperClassName}\n description={description}\n hideLabel={hideLabel || !!ariaLabelledBy}\n id={id}\n invalid={invalid}\n label={label}\n size={size}\n >\n {({ descriptionId, inputId }) => (\n <input\n {...restProps}\n {...autoCompleteBlockingProps}\n aria-describedby={descriptionId}\n aria-invalid={invalid || undefined}\n aria-label={hideLabel ? ariaLabel || (label as string) : ariaLabel}\n aria-labelledby={ariaLabelledBy}\n autoComplete={autoComplete}\n id={inputId}\n onFocus={handleFocus}\n ref={ref}\n type={type}\n />\n )}\n </InputTextBase>\n )\n }\n)\n\nInput.displayName = \"Input\"\n"],"names":["React"],"mappings":";;;;AAmEA
|
|
1
|
+
{"version":3,"file":"Input.js","sources":["../../../src/components/input/Input.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { InputTextBase } from \"@components/input-text-base\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type InputHTMLAttributes } from \"react\"\n\nexport type InputSize = \"lg\" | \"md\"\n\nexport type InputType =\n | \"email\"\n | \"number\"\n | \"password\"\n | \"search\"\n | \"tel\"\n | \"text\"\n | \"url\"\n\ninterface InputBaseProps {\n /** If true, the input width grows to fit content. */\n autoWidth?: boolean\n /** Helper text displayed below the input. Styled as an error when `invalid`. */\n description?: string\n /** Whether the input is in an invalid state. */\n invalid?: boolean\n /** If true, all text is selected when the input receives focus. */\n selectTextOnFocus?: boolean\n /** The size of the input. */\n size?: InputSize\n /** Supported input types — defaults to 'text' */\n type?: InputType\n}\n\ninterface InputWithVisibleLabel extends InputBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel?: false\n /** The label text for the input. */\n label: React.ReactNode\n}\n\ninterface InputWithHiddenLabel extends InputBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel: true\n /** The label text for the input. Must be a string when hidden. */\n label: string\n}\n\ninterface InputWithAriaLabelledBy extends InputBaseProps {\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type InputProps =\n | InputWithAriaLabelledBy\n | InputWithHiddenLabel\n | InputWithVisibleLabel\n\n/**\n * Combines standard HTML input attributes with custom Input props.\n * Omits 'size' and 'type' from HTML attributes to avoid conflict with our strict types.\n */\nexport type InputElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof InputProps | \"size\" | \"type\"\n> &\n InputProps\n\n/**\n * A text input component that renders as an HTML `<input>` with a label and\n * optional description. Supports the standard text-like input types\n * (`text`, `email`, `password`, `search`, `tel`, `url`, `number`), invalid\n * state, and `lg`/`md` sizing.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-input--docs | Storybook Documentation}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport const Input = forwardRef<HTMLInputElement, InputElementProps>(\n function Input(\n {\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n autoComplete,\n autoWidth,\n className,\n description,\n hideLabel,\n id,\n invalid,\n label,\n onFocus,\n selectTextOnFocus,\n size = \"md\",\n type = \"text\",\n ...restProps\n }: InputElementProps,\n ref\n ) {\n const autoCompleteBlockingProps =\n autoComplete === \"off\"\n ? {\n \"data-1p-ignore\": true,\n \"data-bwignore\": true,\n \"data-form-type\": \"other\",\n \"data-lpignore\": true,\n }\n : {}\n\n const handleFocus = selectTextOnFocus\n ? (event: React.FocusEvent<HTMLInputElement>) => {\n try {\n event.currentTarget.select()\n } catch {\n // Some input types (e.g. number) do not support text selection.\n }\n onFocus?.(event)\n }\n : onFocus\n\n const wrapperClassName = classNames(\n { \"tds-input--auto-width\": autoWidth },\n className\n )\n\n return (\n <InputTextBase\n className={wrapperClassName}\n description={description}\n hideLabel={hideLabel || !!ariaLabelledBy}\n id={id}\n invalid={invalid}\n label={label}\n size={size}\n >\n {({ descriptionId, inputId }) => (\n <input\n {...restProps}\n {...autoCompleteBlockingProps}\n aria-describedby={descriptionId}\n aria-invalid={invalid || undefined}\n aria-label={hideLabel ? ariaLabel || (label as string) : ariaLabel}\n aria-labelledby={ariaLabelledBy}\n autoComplete={autoComplete}\n id={inputId}\n onFocus={handleFocus}\n ref={ref}\n type={type}\n />\n )}\n </InputTextBase>\n )\n }\n)\n\nInput.displayName = \"Input\"\n"],"names":["React"],"mappings":";;;;AAmEA;;;;;;;;;AASG;MACU,KAAK,GAAG,UAAU,CAC7B,SAAS,KAAK,CACZ,EACE,YAAY,EAAE,SAAS,EACvB,iBAAiB,EAAE,cAAc,EACjC,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,EAAE,EACF,OAAO,EACP,KAAK,EACL,OAAO,EACP,iBAAiB,EACjB,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,MAAM,EACb,GAAG,SAAS,EACM,EACpB,GAAG,EAAA;AAEH,IAAA,MAAM,yBAAyB,GAC7B,YAAY,KAAK;AACf,UAAE;AACE,YAAA,gBAAgB,EAAE,IAAI;AACtB,YAAA,eAAe,EAAE,IAAI;AACrB,YAAA,gBAAgB,EAAE,OAAO;AACzB,YAAA,eAAe,EAAE,IAAI;AACtB;UACD,EAAE;IAER,MAAM,WAAW,GAAG;AAClB,UAAE,CAAC,KAAyC,KAAI;AAC5C,YAAA,IAAI;AACF,gBAAA,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE;YAC9B;AAAE,YAAA,MAAM;;YAER;AACA,YAAA,OAAO,GAAG,KAAK,CAAC;QAClB;UACA,OAAO;AAEX,IAAA,MAAM,gBAAgB,GAAG,UAAU,CACjC,EAAE,uBAAuB,EAAE,SAAS,EAAE,EACtC,SAAS,CACV;IAED,QACEA,6BAAC,aAAa,EAAA,EACZ,SAAS,EAAE,gBAAgB,EAC3B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,IAAI,CAAC,CAAC,cAAc,EACxC,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EAAA,EAET,CAAC,EAAE,aAAa,EAAE,OAAO,EAAE,MAC1BA,cAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,GACM,SAAS,EAAA,GACT,yBAAyB,sBACX,aAAa,EAAA,cAAA,EACjB,OAAO,IAAI,SAAS,gBACtB,SAAS,GAAG,SAAS,IAAK,KAAgB,GAAG,SAAS,qBACjD,cAAc,EAC/B,YAAY,EAAE,YAAY,EAC1B,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,WAAW,EACpB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EAAA,CACV,CACH,CACa;AAEpB,CAAC;AAGH,KAAK,CAAC,WAAW,GAAG,OAAO;;;;"}
|
|
@@ -12,6 +12,7 @@ export type LinkProps = Omit<BaseLinkElementProps, "label"> & {
|
|
|
12
12
|
*
|
|
13
13
|
* @component
|
|
14
14
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-link--docs | Storybook Documentation}
|
|
15
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
15
16
|
*/
|
|
16
17
|
export declare const Link: React.ForwardRefExoticComponent<Omit<BaseLinkElementProps, "label"> & {
|
|
17
18
|
children?: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/components/link/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAE1B,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAY,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAE3D,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,GAAG;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/components/link/Link.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAE1B,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAY,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAE3D,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,oBAAoB,EAAE,OAAO,CAAC,GAAG;IAC5D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI;eAbJ,KAAK,CAAC,SAAS;YAClB,MAAM;2CAgBf,CAAA"}
|
|
@@ -8,6 +8,7 @@ import { BaseLink } from './BaseLink.js';
|
|
|
8
8
|
*
|
|
9
9
|
* @component
|
|
10
10
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-link--docs | Storybook Documentation}
|
|
11
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
11
12
|
*/
|
|
12
13
|
const Link = forwardRef(({ href, ...restProps }, ref) => {
|
|
13
14
|
return React__default.createElement(BaseLink, { href: href, ref: ref, ...restProps });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Link.js","sources":["../../../src/components/link/Link.tsx"],"sourcesContent":["import \"../button/btn.css\"\n\nimport React, { forwardRef } from \"react\"\n\nimport { BaseLink, BaseLinkElementProps } from \"./BaseLink\"\n\nexport type LinkProps = Omit<BaseLinkElementProps, \"label\"> & {\n children?: React.ReactNode\n label?: string\n}\n\n/**\n * A link component that renders as an HTML `<a>` element with button-like\n * styling. Use for navigation; for actions that don't change the URL, use\n * `Button` instead.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-link--docs | Storybook Documentation}\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(\n ({ href, ...restProps }: LinkProps, ref) => {\n return <BaseLink href={href} ref={ref} {...restProps} />\n }\n)\n\nLink.displayName = \"Link\"\n"],"names":["React"],"mappings":";;;AAWA
|
|
1
|
+
{"version":3,"file":"Link.js","sources":["../../../src/components/link/Link.tsx"],"sourcesContent":["import \"../button/btn.css\"\n\nimport React, { forwardRef } from \"react\"\n\nimport { BaseLink, BaseLinkElementProps } from \"./BaseLink\"\n\nexport type LinkProps = Omit<BaseLinkElementProps, \"label\"> & {\n children?: React.ReactNode\n label?: string\n}\n\n/**\n * A link component that renders as an HTML `<a>` element with button-like\n * styling. Use for navigation; for actions that don't change the URL, use\n * `Button` instead.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-link--docs | Storybook Documentation}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(\n ({ href, ...restProps }: LinkProps, ref) => {\n return <BaseLink href={href} ref={ref} {...restProps} />\n }\n)\n\nLink.displayName = \"Link\"\n"],"names":["React"],"mappings":";;;AAWA;;;;;;;;AAQG;AACI,MAAM,IAAI,GAAG,UAAU,CAC5B,CAAC,EAAE,IAAI,EAAE,GAAG,SAAS,EAAa,EAAE,GAAG,KAAI;AACzC,IAAA,OAAOA,cAAA,CAAA,aAAA,CAAC,QAAQ,EAAA,EAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAA,GAAM,SAAS,GAAI;AAC1D,CAAC;AAGH,IAAI,CAAC,WAAW,GAAG,MAAM;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberStepper.d.ts","sourceRoot":"","sources":["../../../src/components/number-stepper/NumberStepper.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"NumberStepper.d.ts","sourceRoot":"","sources":["../../../src/components/number-stepper/NumberStepper.tsx"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAA;AAC1B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,aAAa,CAAA;AAGpB,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;AAEhF,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAML,KAAK,gBAAgB,IAAI,oBAAoB,EAE9C,MAAM,mCAAmC,CAAA;AAE1C,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,CAAA;AAE3C,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAA;IACb,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,sCAAsC;IACtC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CACzB;AAED,KAAK,0BAA0B,GAC3B,UAAU,GACV,QAAQ,GACR,MAAM,GACN,UAAU,GACV,oBAAoB,CAAA;AAExB,KAAK,6BAA6B,GAC9B,eAAe,GACf,MAAM,GACN,UAAU,GACV,MAAM,GACN,OAAO,CAAA;AAEX,MAAM,MAAM,yBAAyB,GAAG,+BAA+B,CACrE,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAC1B,6BAA6B,CAC9B,CAAA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,KAAK,EACL,GAAG,EACH,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,IAAW,EACX,GAAG,SAAS,EACb,EAAE,yBAAyB,qBAmD3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberStepper.js","sources":["../../../src/components/number-stepper/NumberStepper.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../
|
|
1
|
+
{"version":3,"file":"NumberStepper.js","sources":["../../../src/components/number-stepper/NumberStepper.tsx"],"sourcesContent":["import \"../button/btn.css\"\nimport \"../field/index.css\"\nimport \"./index.css\"\n\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport classNames from \"classnames\"\nimport React from \"react\"\nimport {\n Button,\n Group,\n Input,\n Label,\n NumberField as AriaNumberField,\n type NumberFieldProps as AriaNumberFieldProps,\n Text,\n} from \"react-aria-components/NumberField\"\n\nexport type NumberStepperSize = \"md\" | \"lg\"\n\nexport interface NumberStepperProps {\n /** The default uncontrolled value. */\n defaultValue?: number\n /** Helper text displayed below the component. Styled as error text when `invalid` is `true`. */\n description?: string\n /** Disables the input and stepper buttons. */\n disabled?: boolean\n /** If `true`, renders the label visually hidden. */\n hideLabel?: boolean\n /** If `true`, applies error styling to the field and description. */\n invalid?: boolean\n /** Accessible label for the field. */\n label: string\n /** Maximum allowed value. */\n max?: number\n /** Minimum allowed value. */\n min?: number\n /** Allows the value to be read but not changed. */\n readOnly?: boolean\n /** If `true`, appends an asterisk after the label text. */\n required?: boolean\n /** The size of the number stepper. */\n size?: NumberStepperSize\n}\n\ntype AriaNumberFieldPropsToOmit =\n | \"children\"\n | \"render\"\n | \"slot\"\n | \"validate\"\n | \"validationBehavior\"\n\ntype AriaNumberFieldPropsToInclude =\n | \"formatOptions\"\n | \"name\"\n | \"onChange\"\n | \"step\"\n | \"value\"\n\nexport type NumberStepperElementProps = CombineAriaPropsWithCustomProps<\n AriaNumberFieldProps,\n NumberStepperProps,\n AriaNumberFieldPropsToOmit,\n AriaNumberFieldPropsToInclude\n>\n\n/**\n * A number stepper component that pairs a numeric input with increment and\n * decrement buttons. Use it when users need to enter or adjust a number by\n * small amounts, such as quantities or counts.\n *\n * Constrain the input with `min`, `max`, and `step`, and customize display\n * (currency, percentage, decimal precision) via the `formatOptions` prop.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-numberstepper--docs | Storybook Documentation}\n */\nexport function NumberStepper({\n className,\n defaultValue,\n description,\n disabled,\n hideLabel,\n invalid,\n label,\n max,\n min,\n readOnly,\n required,\n size = \"md\",\n ...restProps\n}: NumberStepperElementProps) {\n const combinedClassName = classNames(\n \"tds-field tds-number-stepper\",\n {\n \"tds-field--lg\": size === \"lg\",\n \"tds-number-stepper--lg\": size === \"lg\",\n },\n className\n )\n\n return (\n <AriaNumberField\n {...restProps}\n aria-label={hideLabel ? label : undefined}\n className={combinedClassName}\n defaultValue={defaultValue}\n isDisabled={disabled}\n isInvalid={invalid}\n isReadOnly={readOnly}\n isRequired={required}\n maxValue={max}\n minValue={min}\n >\n {!hideLabel && <Label className=\"tds-field-label\">{label}</Label>}\n <Group className=\"tds-field-control tds-number-stepper-field\">\n <Input className=\"tds-number-stepper-input\" />\n <Button\n className=\"tds-btn tds-btn--infield tds-number-stepper-button\"\n slot=\"decrement\"\n >\n <Icon aria-hidden symbol=\"general#minus\" />\n </Button>\n <Button\n className=\"tds-btn tds-btn--infield tds-number-stepper-button\"\n slot=\"increment\"\n >\n <Icon aria-hidden symbol=\"general#plus\" />\n </Button>\n </Group>\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 </AriaNumberField>\n )\n}\n"],"names":["React","AriaNumberField"],"mappings":";;;;;AAkEA;;;;;;;;;;AAUG;AACG,SAAU,aAAa,CAAC,EAC5B,SAAS,EACT,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,KAAK,EACL,GAAG,EACH,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,IAAI,GAAG,IAAI,EACX,GAAG,SAAS,EACc,EAAA;AAC1B,IAAA,MAAM,iBAAiB,GAAG,UAAU,CAClC,8BAA8B,EAC9B;QACE,eAAe,EAAE,IAAI,KAAK,IAAI;QAC9B,wBAAwB,EAAE,IAAI,KAAK,IAAI;KACxC,EACD,SAAS,CACV;IAED,QACEA,6BAACC,WAAe,EAAA,EAAA,GACV,SAAS,EAAA,YAAA,EACD,SAAS,GAAG,KAAK,GAAG,SAAS,EACzC,SAAS,EAAE,iBAAiB,EAC5B,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,QAAQ,EACpB,SAAS,EAAE,OAAO,EAClB,UAAU,EAAE,QAAQ,EACpB,UAAU,EAAE,QAAQ,EACpB,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,GAAG,EAAA;QAEZ,CAAC,SAAS,IAAID,cAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EAAC,SAAS,EAAC,iBAAiB,EAAA,EAAE,KAAK,CAAS;AACjE,QAAAA,cAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EAAC,SAAS,EAAC,4CAA4C,EAAA;AAC3D,YAAAA,cAAA,CAAA,aAAA,CAAC,KAAK,EAAA,EAAC,SAAS,EAAC,0BAA0B,EAAA,CAAG;YAC9CA,cAAA,CAAA,aAAA,CAAC,MAAM,IACL,SAAS,EAAC,oDAAoD,EAC9D,IAAI,EAAC,WAAW,EAAA;AAEhB,gBAAAA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAA,aAAA,EAAA,IAAA,EAAa,MAAM,EAAC,eAAe,GAAG,CACpC;YACTA,cAAA,CAAA,aAAA,CAAC,MAAM,IACL,SAAS,EAAC,oDAAoD,EAC9D,IAAI,EAAC,WAAW,EAAA;AAEhB,gBAAAA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAA,aAAA,EAAA,IAAA,EAAa,MAAM,EAAC,cAAc,EAAA,CAAG,CACnC,CACH;QACP,WAAW,KACVA,cAAA,CAAA,aAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,uBAAuB,EAAC,IAAI,EAAC,aAAa,EAAA;YACxDA,cAAA,CAAA,aAAA,CAAC,IAAI,yBAEH,SAAS,EAAC,oCAAoC,EAC9C,MAAM,EAAC,8BAA8B,EAAA,CACrC;AACD,YAAA,WAAW,CACP,CACR,CACe;AAEtB;;;;"}
|
|
@@ -40,6 +40,7 @@ export type RadioElementProps = Omit<InputHTMLAttributes<HTMLInputElement>, keyo
|
|
|
40
40
|
*
|
|
41
41
|
* @component
|
|
42
42
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-radio--docs | Storybook Documentation}
|
|
43
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
43
44
|
*/
|
|
44
45
|
export declare const Radio: React.ForwardRefExoticComponent<RadioElementProps & React.RefAttributes<HTMLInputElement>>;
|
|
45
46
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/radio/Radio.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAE9D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,UAAU,cAAc;IACtB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,cAAe,SAAQ,cAAc;IAC7C,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB;;;;;OAKG;IACH,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,uBAAuB,CAAA;AAEjE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,CAC1B,GACC,UAAU,CAAA;AAEZ
|
|
1
|
+
{"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/radio/Radio.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAE,EAAc,mBAAmB,EAAE,MAAM,OAAO,CAAA;AAE9D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnC,UAAU,cAAc;IACtB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAED,UAAU,cAAe,SAAQ,cAAc;IAC7C,iBAAiB,CAAC,EAAE,KAAK,CAAA;IACzB;;;;;OAKG;IACH,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,UAAU,uBAAwB,SAAQ,cAAc;IACtD,iBAAiB,EAAE,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,uBAAuB,CAAA;AAEjE,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAClC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,UAAU,GAAG,MAAM,CAC1B,GACC,UAAU,CAAA;AAEZ;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,KAAK,4FAuCjB,CAAA"}
|
|
@@ -17,6 +17,7 @@ import React__default, { forwardRef } from 'react';
|
|
|
17
17
|
*
|
|
18
18
|
* @component
|
|
19
19
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-radio--docs | Storybook Documentation}
|
|
20
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
20
21
|
*/
|
|
21
22
|
const Radio = forwardRef(({ className, description, id, label, size = "md", ...restProps }, ref) => {
|
|
22
23
|
const combinedClassName = classNames("tds-radio", size && size === "sm" && `tds-radio--sm`, className);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Radio.js","sources":["../../../src/components/radio/Radio.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, InputHTMLAttributes } from \"react\"\n\nexport type RadioSize = \"md\" | \"sm\"\n\ninterface RadioBaseProps {\n /** Optional description text that appears below the radio label. */\n description?: string\n /** The name of the radio group. All radios in the group must have the same name. */\n name: string\n /** The size of the radio. */\n size?: RadioSize\n}\n\ninterface RadioWithLabel extends RadioBaseProps {\n \"aria-labelledby\"?: never\n /**\n * Label content for the radio. When using non-string content\n * (e.g. JSX), it must not contain interactive elements. This\n * includes native HTML elements such as `<a>` and `<button>`, as\n * well as Tapestry or Tapestry-React interactive components.\n */\n label: React.ReactNode\n}\n\ninterface RadioWithAriaLabelledBy extends RadioBaseProps {\n \"aria-labelledby\": string\n label?: never\n}\n\nexport type RadioProps = RadioWithLabel | RadioWithAriaLabelledBy\n\nexport type RadioElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof RadioProps | \"type\"\n> &\n RadioProps\n\n/**\n * A radio component that renders as a radio input with label.\n * Supports various sizes.\n * Must have a name attribute.\n *\n * **Required:** You must provide either:\n * - `label` - Label content for the radio\n * - `aria-labelledby` - ID of an external element that provides the label\n *\n * When using non-string content for `label` (e.g. JSX), it must not contain\n * interactive elements. This includes native HTML elements such as `<a>` and\n * `<button>`, as well as Tapestry or Tapestry-React interactive components.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-radio--docs | Storybook Documentation}\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioElementProps>(\n (\n {\n className,\n description,\n id,\n label,\n size = \"md\",\n ...restProps\n }: RadioElementProps,\n ref\n ) => {\n const combinedClassName = classNames(\n \"tds-radio\",\n size && size === \"sm\" && `tds-radio--sm`,\n className\n )\n\n const stableId = useId()\n const radioId = id || `tds-radio-${stableId}`\n\n return (\n <div className={combinedClassName}>\n <input\n {...restProps}\n aria-describedby={description ? `${radioId}-description` : undefined}\n id={radioId}\n ref={ref}\n type=\"radio\"\n />\n {label && <label htmlFor={radioId}>{label}</label>}\n {description && (\n <p id={`${radioId}-description`} className=\"tds-radio-description\">\n {description}\n </p>\n )}\n </div>\n )\n }\n)\n\nRadio.displayName = \"Radio\"\n"],"names":["React"],"mappings":";;;;AAyCA
|
|
1
|
+
{"version":3,"file":"Radio.js","sources":["../../../src/components/radio/Radio.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, InputHTMLAttributes } from \"react\"\n\nexport type RadioSize = \"md\" | \"sm\"\n\ninterface RadioBaseProps {\n /** Optional description text that appears below the radio label. */\n description?: string\n /** The name of the radio group. All radios in the group must have the same name. */\n name: string\n /** The size of the radio. */\n size?: RadioSize\n}\n\ninterface RadioWithLabel extends RadioBaseProps {\n \"aria-labelledby\"?: never\n /**\n * Label content for the radio. When using non-string content\n * (e.g. JSX), it must not contain interactive elements. This\n * includes native HTML elements such as `<a>` and `<button>`, as\n * well as Tapestry or Tapestry-React interactive components.\n */\n label: React.ReactNode\n}\n\ninterface RadioWithAriaLabelledBy extends RadioBaseProps {\n \"aria-labelledby\": string\n label?: never\n}\n\nexport type RadioProps = RadioWithLabel | RadioWithAriaLabelledBy\n\nexport type RadioElementProps = Omit<\n InputHTMLAttributes<HTMLInputElement>,\n keyof RadioProps | \"type\"\n> &\n RadioProps\n\n/**\n * A radio component that renders as a radio input with label.\n * Supports various sizes.\n * Must have a name attribute.\n *\n * **Required:** You must provide either:\n * - `label` - Label content for the radio\n * - `aria-labelledby` - ID of an external element that provides the label\n *\n * When using non-string content for `label` (e.g. JSX), it must not contain\n * interactive elements. This includes native HTML elements such as `<a>` and\n * `<button>`, as well as Tapestry or Tapestry-React interactive components.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-radio--docs | Storybook Documentation}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport const Radio = forwardRef<HTMLInputElement, RadioElementProps>(\n (\n {\n className,\n description,\n id,\n label,\n size = \"md\",\n ...restProps\n }: RadioElementProps,\n ref\n ) => {\n const combinedClassName = classNames(\n \"tds-radio\",\n size && size === \"sm\" && `tds-radio--sm`,\n className\n )\n\n const stableId = useId()\n const radioId = id || `tds-radio-${stableId}`\n\n return (\n <div className={combinedClassName}>\n <input\n {...restProps}\n aria-describedby={description ? `${radioId}-description` : undefined}\n id={radioId}\n ref={ref}\n type=\"radio\"\n />\n {label && <label htmlFor={radioId}>{label}</label>}\n {description && (\n <p id={`${radioId}-description`} className=\"tds-radio-description\">\n {description}\n </p>\n )}\n </div>\n )\n }\n)\n\nRadio.displayName = \"Radio\"\n"],"names":["React"],"mappings":";;;;AAyCA;;;;;;;;;;;;;;;;AAgBG;AACI,MAAM,KAAK,GAAG,UAAU,CAC7B,CACE,EACE,SAAS,EACT,WAAW,EACX,EAAE,EACF,KAAK,EACL,IAAI,GAAG,IAAI,EACX,GAAG,SAAS,EACM,EACpB,GAAG,KACD;AACF,IAAA,MAAM,iBAAiB,GAAG,UAAU,CAClC,WAAW,EACX,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,CAAA,aAAA,CAAe,EACxC,SAAS,CACV;AAED,IAAA,MAAM,QAAQ,GAAG,KAAK,EAAE;AACxB,IAAA,MAAM,OAAO,GAAG,EAAE,IAAI,CAAA,UAAA,EAAa,QAAQ,EAAE;AAE7C,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,iBAAiB,EAAA;QAC/BA,cAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,GACM,SAAS,EAAA,kBAAA,EACK,WAAW,GAAG,CAAA,EAAG,OAAO,CAAA,YAAA,CAAc,GAAG,SAAS,EACpE,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,OAAO,EAAA,CACZ;AACD,QAAA,KAAK,IAAIA,cAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAO,OAAO,EAAE,OAAO,EAAA,EAAG,KAAK,CAAS;AACjD,QAAA,WAAW,KACVA,cAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAG,EAAE,EAAE,CAAA,EAAG,OAAO,CAAA,YAAA,CAAc,EAAE,SAAS,EAAC,uBAAuB,EAAA,EAC/D,WAAW,CACV,CACL,CACG;AAEV,CAAC;AAGH,KAAK,CAAC,WAAW,GAAG,OAAO;;;;"}
|
|
@@ -145,6 +145,7 @@ export type SelectElementProps = NativeSelectElementProps | ComplexSelectElement
|
|
|
145
145
|
*
|
|
146
146
|
* @component
|
|
147
147
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-select--docs | Storybook Documentation}
|
|
148
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
148
149
|
*/
|
|
149
150
|
export declare const Select: React.ForwardRefExoticComponent<SelectElementProps & React.RefAttributes<HTMLSelectElement>>;
|
|
150
151
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/select/Select.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/select/Select.tsx"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ function normalizeSelectValue(value) {
|
|
|
23
23
|
*
|
|
24
24
|
* @component
|
|
25
25
|
* @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-select--docs | Storybook Documentation}
|
|
26
|
+
* @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}
|
|
26
27
|
*/
|
|
27
28
|
const Select = forwardRef(function Select(props, ref) {
|
|
28
29
|
const { "aria-label": userAriaLabel, "aria-labelledby": userAriaLabelledBy, className, complex, defaultValue, description, hideLabel, id, invalid, label, onChange, options, placeholder, required, size, value, ...restProps } = props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.js","sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type SelectHTMLAttributes, useRef } from \"react\"\n\nimport { SelectNative } from \"./SelectNative\"\nimport { SelectPopover } from \"./SelectPopover\"\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\nexport type SelectSize = \"lg\" | \"md\"\n\n/**\n * String-labelled option variant. Valid in both native (`complex={false}`)\n * and complex (`complex={true}`) modes. The `label` doubles as the type-ahead\n * search target.\n */\nexport interface SelectOptionWithTextLabel {\n /** Arbitrary `data-*` attributes are forwarded to the rendered option. */\n [key: `data-${string}`]: boolean | number | string | undefined\n /** Whether this option is non-interactive. */\n disabled?: boolean\n divider?: never\n /** Displayed as the option content and used for type-ahead matching. */\n label: string\n textValue?: never\n /** Unique identifier for the option. */\n value: string\n}\n\n/**\n * Rich-content option variant. The popover (`complex={true}`) renders the\n * `label` node directly; the native `<select>` (`complex={false}`) falls back\n * to `textValue` for the visible text. Requires a plain-text `textValue` so\n * type-ahead matching, screen reader announcements, and the native fallback\n * all have something stable to use.\n */\nexport interface SelectOptionWithNodeLabel {\n /** Arbitrary `data-*` attributes are forwarded to the rendered option. */\n [key: `data-${string}`]: boolean | number | string | undefined\n /** Whether this option is non-interactive. */\n disabled?: boolean\n divider?: never\n /**\n * Option content. Rendered as JSX in complex mode; in native mode, the\n * visible text comes from `textValue` instead.\n */\n label: React.ReactNode\n /**\n * Plain-text fallback for type-ahead matching, screen reader\n * announcements, and the native `<select>`'s visible option text when\n * `label` is a React node.\n */\n textValue: string\n /** Unique identifier for the option. */\n value: string\n}\n\n/**\n * Visual-separator option variant. Renders a divider line between options\n * (or between groups of options). Carries no value of its own.\n */\nexport interface SelectOptionDivider {\n disabled?: never\n /** Renders a visual separator between options. */\n divider: true\n label?: never\n textValue?: never\n value?: never\n}\n\nexport type SelectOption =\n | SelectOptionDivider\n | SelectOptionWithNodeLabel\n | SelectOptionWithTextLabel\n\n/**\n * A group entry in `Select`'s `options` array. Renders a heading above its\n * `options` and nests them visually beneath it.\n */\nexport interface SelectOptionsGroup {\n /**\n * Whether all options in this group are non-interactive. Disables every\n * nested option regardless of its own `disabled` flag.\n */\n disabled?: boolean\n /** Visible heading displayed above the group's options. */\n label: string\n /** The selectable options nested under this group. */\n options: SelectOption[]\n}\n\nexport type SelectItem = SelectOption | SelectOptionsGroup\n\n// ---------------------------------------------------------------------------\n// Select component props\n// ---------------------------------------------------------------------------\n\ninterface SelectBaseProps {\n /**\n * When true, renders as a popover listbox instead of a native `<select>`.\n * Enables rich content in options (icons, descriptions).\n */\n complex?: boolean\n /**\n * Helper text displayed below the select. Styled as error text when\n * `invalid`. Defaults to `\"Please select an option\"` when `invalid` is true\n * and no description is provided.\n */\n description?: string\n /**\n * Whether the select is in an invalid state. Shows the default description\n * if none is provided.\n */\n invalid?: boolean\n /** A flat or mixed array of options and option groups. */\n options: SelectItem[]\n /** Placeholder text shown when no option is selected. Defaults to `\"Select an option\"`. */\n placeholder?: string\n /** The size of the select. */\n size?: SelectSize\n}\n\ninterface SelectWithVisibleLabel extends SelectBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel?: false\n /**\n * The label text for the select. Required unless `aria-label` or\n * `aria-labelledby` is provided.\n */\n label: string\n}\n\ninterface SelectWithHiddenLabel extends SelectBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel: true\n /** The label text for the select. Must be a string when hidden. */\n label: string\n}\n\ninterface SelectWithAriaLabel extends SelectBaseProps {\n /** Accessible label for the select. Use when no visible label exists. */\n \"aria-label\": string\n hideLabel?: never\n label?: never\n}\n\ninterface SelectWithAriaLabelledBy extends SelectBaseProps {\n /**\n * ID of an external label element. Use instead of `label` when a visible\n * label exists elsewhere on the page.\n */\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type SelectProps =\n | SelectWithAriaLabel\n | SelectWithAriaLabelledBy\n | SelectWithHiddenLabel\n | SelectWithVisibleLabel\n\ntype BaseSelectElementProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n keyof SelectProps | \"multiple\" | \"size\"\n>\n\nexport type NativeSelectElementProps = BaseSelectElementProps &\n SelectProps & {\n complex?: false\n }\n\nexport type ComplexSelectElementProps = BaseSelectElementProps &\n SelectProps & {\n complex: true\n }\n\nexport type SelectElementProps =\n | NativeSelectElementProps\n | ComplexSelectElementProps\n\nfunction normalizeSelectValue(\n value:\n | NativeSelectElementProps[\"defaultValue\"]\n | NativeSelectElementProps[\"value\"]\n | ComplexSelectElementProps[\"defaultValue\"]\n | ComplexSelectElementProps[\"value\"]\n) {\n if (value === undefined || value === null) return undefined\n if (Array.isArray(value)) return value[0]\n return String(value)\n}\n\n// ---------------------------------------------------------------------------\n// Select (public)\n// ---------------------------------------------------------------------------\n\n/**\n * A select component for choosing a single value from a list of options.\n * By default renders a native `<select>`; set `complex` to render a popover\n * listbox that supports rich option content (icons, descriptions). Supports\n * option groups, dividers, invalid state, and `lg`/`md` sizing.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-select--docs | Storybook Documentation}\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectElementProps>(\n function Select(props: SelectElementProps, ref) {\n const {\n \"aria-label\": userAriaLabel,\n \"aria-labelledby\": userAriaLabelledBy,\n className,\n complex,\n defaultValue,\n description,\n hideLabel,\n id,\n invalid,\n label,\n onChange,\n options,\n placeholder,\n required,\n size,\n value,\n ...restProps\n } = props\n\n const triggerRef = useRef<HTMLButtonElement>(null)\n const stableId = useId()\n const controlId = id || `tds-select-${stableId}`\n const labelId = `${controlId}-label`\n const resolvedDescription =\n description || (invalid ? \"Please select an option\" : undefined)\n const descriptionId = resolvedDescription\n ? `${controlId}-description`\n : undefined\n const computedClassName = classNames(\n \"tds-select\",\n {\n \"tds-select--invalid\": invalid,\n \"tds-select--lg\": size === \"lg\",\n \"tds-select--required\": required,\n },\n className\n )\n\n const normalizedDefaultValue = normalizeSelectValue(defaultValue)\n const normalizedValue = normalizeSelectValue(value)\n\n const computedDefaultValue =\n normalizedDefaultValue === undefined && normalizedValue === undefined\n ? \"\"\n : normalizedDefaultValue\n const effectivePlaceholder =\n normalizedDefaultValue !== undefined && normalizedDefaultValue !== \"\"\n ? null\n : placeholder || \"Select an option\"\n const showLabel = !!label && !hideLabel\n const computedAriaLabel = userAriaLabel ?? (hideLabel ? label : undefined)\n const computedAriaLabelledBy =\n userAriaLabelledBy ??\n (computedAriaLabel || !showLabel ? undefined : labelId)\n\n const sharedControlProps = {\n ...restProps,\n \"aria-describedby\": descriptionId,\n \"aria-label\": computedAriaLabel,\n \"aria-labelledby\": computedAriaLabelledBy,\n defaultValue: computedDefaultValue,\n invalid,\n options,\n placeholder: effectivePlaceholder,\n required,\n value: normalizedValue,\n }\n\n const handleComplexLabelClick = () => triggerRef.current?.focus()\n\n const SelectComponent = complex ? SelectPopover : SelectNative\n\n return (\n <div className={computedClassName}>\n {showLabel &&\n (complex ? (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -- mirrors native label click-to-focus; keyboard users interact with the combobox directly\n <div\n className=\"tds-select-label\"\n id={labelId}\n onClick={handleComplexLabelClick}\n >\n {label}\n </div>\n ) : (\n <label htmlFor={controlId} id={labelId}>\n {label}\n </label>\n ))}\n <SelectComponent\n {...sharedControlProps}\n ref={ref}\n id={controlId}\n onChange={onChange}\n {...(complex && { triggerRef })}\n />\n {resolvedDescription && descriptionId && (\n <p className=\"tds-select-description\" id={descriptionId}>\n <Icon\n aria-hidden\n className=\"tds-select-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {resolvedDescription}\n </p>\n )}\n </div>\n )\n }\n)\n\nSelect.displayName = \"Select\"\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Select.js","sources":["../../../src/components/select/Select.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport Icon from \"@utilities/Icon\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, { forwardRef, type SelectHTMLAttributes, useRef } from \"react\"\n\nimport { SelectNative } from \"./SelectNative\"\nimport { SelectPopover } from \"./SelectPopover\"\n\n// ---------------------------------------------------------------------------\n// Shared types\n// ---------------------------------------------------------------------------\n\nexport type SelectSize = \"lg\" | \"md\"\n\n/**\n * String-labelled option variant. Valid in both native (`complex={false}`)\n * and complex (`complex={true}`) modes. The `label` doubles as the type-ahead\n * search target.\n */\nexport interface SelectOptionWithTextLabel {\n /** Arbitrary `data-*` attributes are forwarded to the rendered option. */\n [key: `data-${string}`]: boolean | number | string | undefined\n /** Whether this option is non-interactive. */\n disabled?: boolean\n divider?: never\n /** Displayed as the option content and used for type-ahead matching. */\n label: string\n textValue?: never\n /** Unique identifier for the option. */\n value: string\n}\n\n/**\n * Rich-content option variant. The popover (`complex={true}`) renders the\n * `label` node directly; the native `<select>` (`complex={false}`) falls back\n * to `textValue` for the visible text. Requires a plain-text `textValue` so\n * type-ahead matching, screen reader announcements, and the native fallback\n * all have something stable to use.\n */\nexport interface SelectOptionWithNodeLabel {\n /** Arbitrary `data-*` attributes are forwarded to the rendered option. */\n [key: `data-${string}`]: boolean | number | string | undefined\n /** Whether this option is non-interactive. */\n disabled?: boolean\n divider?: never\n /**\n * Option content. Rendered as JSX in complex mode; in native mode, the\n * visible text comes from `textValue` instead.\n */\n label: React.ReactNode\n /**\n * Plain-text fallback for type-ahead matching, screen reader\n * announcements, and the native `<select>`'s visible option text when\n * `label` is a React node.\n */\n textValue: string\n /** Unique identifier for the option. */\n value: string\n}\n\n/**\n * Visual-separator option variant. Renders a divider line between options\n * (or between groups of options). Carries no value of its own.\n */\nexport interface SelectOptionDivider {\n disabled?: never\n /** Renders a visual separator between options. */\n divider: true\n label?: never\n textValue?: never\n value?: never\n}\n\nexport type SelectOption =\n | SelectOptionDivider\n | SelectOptionWithNodeLabel\n | SelectOptionWithTextLabel\n\n/**\n * A group entry in `Select`'s `options` array. Renders a heading above its\n * `options` and nests them visually beneath it.\n */\nexport interface SelectOptionsGroup {\n /**\n * Whether all options in this group are non-interactive. Disables every\n * nested option regardless of its own `disabled` flag.\n */\n disabled?: boolean\n /** Visible heading displayed above the group's options. */\n label: string\n /** The selectable options nested under this group. */\n options: SelectOption[]\n}\n\nexport type SelectItem = SelectOption | SelectOptionsGroup\n\n// ---------------------------------------------------------------------------\n// Select component props\n// ---------------------------------------------------------------------------\n\ninterface SelectBaseProps {\n /**\n * When true, renders as a popover listbox instead of a native `<select>`.\n * Enables rich content in options (icons, descriptions).\n */\n complex?: boolean\n /**\n * Helper text displayed below the select. Styled as error text when\n * `invalid`. Defaults to `\"Please select an option\"` when `invalid` is true\n * and no description is provided.\n */\n description?: string\n /**\n * Whether the select is in an invalid state. Shows the default description\n * if none is provided.\n */\n invalid?: boolean\n /** A flat or mixed array of options and option groups. */\n options: SelectItem[]\n /** Placeholder text shown when no option is selected. Defaults to `\"Select an option\"`. */\n placeholder?: string\n /** The size of the select. */\n size?: SelectSize\n}\n\ninterface SelectWithVisibleLabel extends SelectBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel?: false\n /**\n * The label text for the select. Required unless `aria-label` or\n * `aria-labelledby` is provided.\n */\n label: string\n}\n\ninterface SelectWithHiddenLabel extends SelectBaseProps {\n /** If true, the label is visually hidden and set as aria-label. */\n hideLabel: true\n /** The label text for the select. Must be a string when hidden. */\n label: string\n}\n\ninterface SelectWithAriaLabel extends SelectBaseProps {\n /** Accessible label for the select. Use when no visible label exists. */\n \"aria-label\": string\n hideLabel?: never\n label?: never\n}\n\ninterface SelectWithAriaLabelledBy extends SelectBaseProps {\n /**\n * ID of an external label element. Use instead of `label` when a visible\n * label exists elsewhere on the page.\n */\n \"aria-labelledby\": string\n hideLabel?: never\n label?: never\n}\n\nexport type SelectProps =\n | SelectWithAriaLabel\n | SelectWithAriaLabelledBy\n | SelectWithHiddenLabel\n | SelectWithVisibleLabel\n\ntype BaseSelectElementProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n keyof SelectProps | \"multiple\" | \"size\"\n>\n\nexport type NativeSelectElementProps = BaseSelectElementProps &\n SelectProps & {\n complex?: false\n }\n\nexport type ComplexSelectElementProps = BaseSelectElementProps &\n SelectProps & {\n complex: true\n }\n\nexport type SelectElementProps =\n | NativeSelectElementProps\n | ComplexSelectElementProps\n\nfunction normalizeSelectValue(\n value:\n | NativeSelectElementProps[\"defaultValue\"]\n | NativeSelectElementProps[\"value\"]\n | ComplexSelectElementProps[\"defaultValue\"]\n | ComplexSelectElementProps[\"value\"]\n) {\n if (value === undefined || value === null) return undefined\n if (Array.isArray(value)) return value[0]\n return String(value)\n}\n\n// ---------------------------------------------------------------------------\n// Select (public)\n// ---------------------------------------------------------------------------\n\n/**\n * A select component for choosing a single value from a list of options.\n * By default renders a native `<select>`; set `complex` to render a popover\n * listbox that supports rich option content (icons, descriptions). Supports\n * option groups, dividers, invalid state, and `lg`/`md` sizing.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/components-select--docs | Storybook Documentation}\n * @see {@link https://github.com/planningcenter/tapestry/tree/main/packages/tapestry-migration-cli | Migration CLI: Available}\n */\nexport const Select = forwardRef<HTMLSelectElement, SelectElementProps>(\n function Select(props: SelectElementProps, ref) {\n const {\n \"aria-label\": userAriaLabel,\n \"aria-labelledby\": userAriaLabelledBy,\n className,\n complex,\n defaultValue,\n description,\n hideLabel,\n id,\n invalid,\n label,\n onChange,\n options,\n placeholder,\n required,\n size,\n value,\n ...restProps\n } = props\n\n const triggerRef = useRef<HTMLButtonElement>(null)\n const stableId = useId()\n const controlId = id || `tds-select-${stableId}`\n const labelId = `${controlId}-label`\n const resolvedDescription =\n description || (invalid ? \"Please select an option\" : undefined)\n const descriptionId = resolvedDescription\n ? `${controlId}-description`\n : undefined\n const computedClassName = classNames(\n \"tds-select\",\n {\n \"tds-select--invalid\": invalid,\n \"tds-select--lg\": size === \"lg\",\n \"tds-select--required\": required,\n },\n className\n )\n\n const normalizedDefaultValue = normalizeSelectValue(defaultValue)\n const normalizedValue = normalizeSelectValue(value)\n\n const computedDefaultValue =\n normalizedDefaultValue === undefined && normalizedValue === undefined\n ? \"\"\n : normalizedDefaultValue\n const effectivePlaceholder =\n normalizedDefaultValue !== undefined && normalizedDefaultValue !== \"\"\n ? null\n : placeholder || \"Select an option\"\n const showLabel = !!label && !hideLabel\n const computedAriaLabel = userAriaLabel ?? (hideLabel ? label : undefined)\n const computedAriaLabelledBy =\n userAriaLabelledBy ??\n (computedAriaLabel || !showLabel ? undefined : labelId)\n\n const sharedControlProps = {\n ...restProps,\n \"aria-describedby\": descriptionId,\n \"aria-label\": computedAriaLabel,\n \"aria-labelledby\": computedAriaLabelledBy,\n defaultValue: computedDefaultValue,\n invalid,\n options,\n placeholder: effectivePlaceholder,\n required,\n value: normalizedValue,\n }\n\n const handleComplexLabelClick = () => triggerRef.current?.focus()\n\n const SelectComponent = complex ? SelectPopover : SelectNative\n\n return (\n <div className={computedClassName}>\n {showLabel &&\n (complex ? (\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions -- mirrors native label click-to-focus; keyboard users interact with the combobox directly\n <div\n className=\"tds-select-label\"\n id={labelId}\n onClick={handleComplexLabelClick}\n >\n {label}\n </div>\n ) : (\n <label htmlFor={controlId} id={labelId}>\n {label}\n </label>\n ))}\n <SelectComponent\n {...sharedControlProps}\n ref={ref}\n id={controlId}\n onChange={onChange}\n {...(complex && { triggerRef })}\n />\n {resolvedDescription && descriptionId && (\n <p className=\"tds-select-description\" id={descriptionId}>\n <Icon\n aria-hidden\n className=\"tds-select-description-invalid-icon\"\n symbol=\"general#exclamation-triangle\"\n />\n {resolvedDescription}\n </p>\n )}\n </div>\n )\n }\n)\n\nSelect.displayName = \"Select\"\n"],"names":["React"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ const SelectNative = forwardRef(function SelectNative({ invalid, options, placeh
|
|
|
35
35
|
return (React__default.createElement("select", { ...restProps, "aria-invalid": invalid ? "true" : undefined, ref: ref },
|
|
36
36
|
isCustom && (React__default.createElement("button", null,
|
|
37
37
|
React__default.createElement("selectedcontent", null))),
|
|
38
|
-
placeholder && (React__default.createElement("option", { disabled: true, hidden: true, value: "" }, placeholder)),
|
|
38
|
+
placeholder && (React__default.createElement("option", { key: `__placeholder__${placeholder}`, disabled: true, hidden: true, value: "" }, placeholder)),
|
|
39
39
|
React__default.createElement(SelectOptions, { items: options, supportsBaseSelect: isCustom })));
|
|
40
40
|
});
|
|
41
41
|
SelectNative.displayName = "SelectNative";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectNative.js","sources":["../../../src/components/select/SelectNative.tsx"],"sourcesContent":["import React, {\n forwardRef,\n type SelectHTMLAttributes,\n useEffect,\n useState,\n} from \"react\"\n\nimport type { SelectItem } from \"./Select\"\nimport { SelectOptions } from \"./SelectOptions\"\n\n// ---------------------------------------------------------------------------\n// base-select feature detection (cached)\n// ---------------------------------------------------------------------------\n\nlet _supportsBaseSelect: boolean | null = null\n\nfunction supportsBaseSelect(): boolean {\n if (_supportsBaseSelect === null) {\n _supportsBaseSelect =\n typeof CSS !== \"undefined\" &&\n typeof CSS.supports === \"function\" &&\n CSS.supports(\"appearance\", \"base-select\")\n }\n return _supportsBaseSelect\n}\n\n// ---------------------------------------------------------------------------\n// JSX augmentation for <selectedcontent>\n// ---------------------------------------------------------------------------\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace JSX {\n interface IntrinsicElements {\n selectedcontent: React.DetailedHTMLProps<\n React.HTMLAttributes<HTMLElement>,\n HTMLElement\n >\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SelectNative\n// ---------------------------------------------------------------------------\n\nexport interface SelectNativeProps {\n /** Triggers invalid state (maps to aria-invalid). */\n invalid?: boolean\n /** Options to render inside the select. */\n options: SelectItem[]\n /** Placeholder text rendered as a disabled hidden option. `null` suppresses the option. */\n placeholder: string | null\n}\n\nexport type SelectNativeElementProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n keyof SelectNativeProps | \"multiple\"\n> &\n SelectNativeProps\n\n/**\n * Internal component. Not intended for direct use — consume `Select` instead.\n *\n * The native `<select>` implementation used by `Select` when `complex` is\n * not set. Renders a real `<select>` element so the browser handles\n * keyboard, type-ahead, and mobile UI natively. When the browser supports\n * `appearance: base-select`, it upgrades to a customizable trigger.\n *\n * @internal\n */\nexport const SelectNative = forwardRef<\n HTMLSelectElement,\n SelectNativeElementProps\n>(function SelectNative(\n { invalid, options, placeholder, ...restProps }: SelectNativeElementProps,\n ref\n) {\n // Keep first render deterministic for SSR/hydration, then detect support on mount.\n const [isCustom, setIsCustom] = useState(false)\n\n useEffect(() => {\n if (supportsBaseSelect()) {\n setIsCustom(true)\n }\n }, [])\n\n return (\n <select\n {...restProps}\n aria-invalid={invalid ? \"true\" : undefined}\n ref={ref}\n >\n {isCustom && (\n <button>\n <selectedcontent />\n </button>\n )}\n {placeholder && (\n <option disabled hidden value=\"\">\n {placeholder}\n </option>\n )}\n <SelectOptions items={options} supportsBaseSelect={isCustom} />\n </select>\n )\n})\n\nSelectNative.displayName = \"SelectNative\"\n"],"names":["React"],"mappings":";;;AAUA;AACA;AACA;AAEA,IAAI,mBAAmB,GAAmB,IAAI;AAE9C,SAAS,kBAAkB,GAAA;AACzB,IAAA,IAAI,mBAAmB,KAAK,IAAI,EAAE;QAChC,mBAAmB;YACjB,OAAO,GAAG,KAAK,WAAW;AAC1B,gBAAA,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU;AAClC,gBAAA,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7C;AACA,IAAA,OAAO,mBAAmB;AAC5B;AAqCA;;;;;;;;;AASG;MACU,YAAY,GAAG,UAAU,CAGpC,SAAS,YAAY,CACrB,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,SAAS,EAA4B,EACzE,GAAG,EAAA;;IAGH,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAE/C,SAAS,CAAC,MAAK;QACb,IAAI,kBAAkB,EAAE,EAAE;YACxB,WAAW,CAAC,IAAI,CAAC;QACnB;IACF,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GACM,SAAS,EAAA,cAAA,EACC,OAAO,GAAG,MAAM,GAAG,SAAS,EAC1C,GAAG,EAAE,GAAG,EAAA;AAEP,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAA;AACE,YAAAA,cAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,IAAA,CAAmB,CACZ,CACV;AACA,QAAA,WAAW,KACVA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAQ,QAAQ,EAAA,IAAA,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"SelectNative.js","sources":["../../../src/components/select/SelectNative.tsx"],"sourcesContent":["import React, {\n forwardRef,\n type SelectHTMLAttributes,\n useEffect,\n useState,\n} from \"react\"\n\nimport type { SelectItem } from \"./Select\"\nimport { SelectOptions } from \"./SelectOptions\"\n\n// ---------------------------------------------------------------------------\n// base-select feature detection (cached)\n// ---------------------------------------------------------------------------\n\nlet _supportsBaseSelect: boolean | null = null\n\nfunction supportsBaseSelect(): boolean {\n if (_supportsBaseSelect === null) {\n _supportsBaseSelect =\n typeof CSS !== \"undefined\" &&\n typeof CSS.supports === \"function\" &&\n CSS.supports(\"appearance\", \"base-select\")\n }\n return _supportsBaseSelect\n}\n\n// ---------------------------------------------------------------------------\n// JSX augmentation for <selectedcontent>\n// ---------------------------------------------------------------------------\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace JSX {\n interface IntrinsicElements {\n selectedcontent: React.DetailedHTMLProps<\n React.HTMLAttributes<HTMLElement>,\n HTMLElement\n >\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// SelectNative\n// ---------------------------------------------------------------------------\n\nexport interface SelectNativeProps {\n /** Triggers invalid state (maps to aria-invalid). */\n invalid?: boolean\n /** Options to render inside the select. */\n options: SelectItem[]\n /** Placeholder text rendered as a disabled hidden option. `null` suppresses the option. */\n placeholder: string | null\n}\n\nexport type SelectNativeElementProps = Omit<\n SelectHTMLAttributes<HTMLSelectElement>,\n keyof SelectNativeProps | \"multiple\"\n> &\n SelectNativeProps\n\n/**\n * Internal component. Not intended for direct use — consume `Select` instead.\n *\n * The native `<select>` implementation used by `Select` when `complex` is\n * not set. Renders a real `<select>` element so the browser handles\n * keyboard, type-ahead, and mobile UI natively. When the browser supports\n * `appearance: base-select`, it upgrades to a customizable trigger.\n *\n * @internal\n */\nexport const SelectNative = forwardRef<\n HTMLSelectElement,\n SelectNativeElementProps\n>(function SelectNative(\n { invalid, options, placeholder, ...restProps }: SelectNativeElementProps,\n ref\n) {\n // Keep first render deterministic for SSR/hydration, then detect support on mount.\n const [isCustom, setIsCustom] = useState(false)\n\n useEffect(() => {\n if (supportsBaseSelect()) {\n setIsCustom(true)\n }\n }, [])\n\n return (\n <select\n {...restProps}\n aria-invalid={invalid ? \"true\" : undefined}\n ref={ref}\n >\n {isCustom && (\n <button>\n <selectedcontent />\n </button>\n )}\n {placeholder && (\n <option key={`__placeholder__${placeholder}`} disabled hidden value=\"\">\n {placeholder}\n </option>\n )}\n <SelectOptions items={options} supportsBaseSelect={isCustom} />\n </select>\n )\n})\n\nSelectNative.displayName = \"SelectNative\"\n"],"names":["React"],"mappings":";;;AAUA;AACA;AACA;AAEA,IAAI,mBAAmB,GAAmB,IAAI;AAE9C,SAAS,kBAAkB,GAAA;AACzB,IAAA,IAAI,mBAAmB,KAAK,IAAI,EAAE;QAChC,mBAAmB;YACjB,OAAO,GAAG,KAAK,WAAW;AAC1B,gBAAA,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU;AAClC,gBAAA,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC;IAC7C;AACA,IAAA,OAAO,mBAAmB;AAC5B;AAqCA;;;;;;;;;AASG;MACU,YAAY,GAAG,UAAU,CAGpC,SAAS,YAAY,CACrB,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,SAAS,EAA4B,EACzE,GAAG,EAAA;;IAGH,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAE/C,SAAS,CAAC,MAAK;QACb,IAAI,kBAAkB,EAAE,EAAE;YACxB,WAAW,CAAC,IAAI,CAAC;QACnB;IACF,CAAC,EAAE,EAAE,CAAC;AAEN,IAAA,QACEA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAA,GACM,SAAS,EAAA,cAAA,EACC,OAAO,GAAG,MAAM,GAAG,SAAS,EAC1C,GAAG,EAAE,GAAG,EAAA;AAEP,QAAA,QAAQ,KACPA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAA;AACE,YAAAA,cAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,IAAA,CAAmB,CACZ,CACV;AACA,QAAA,WAAW,KACVA,cAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAQ,GAAG,EAAE,CAAA,eAAA,EAAkB,WAAW,CAAA,CAAE,EAAE,QAAQ,EAAA,IAAA,EAAC,MAAM,QAAC,KAAK,EAAC,EAAE,EAAA,EACnE,WAAW,CACL,CACV;AACD,QAAAA,cAAA,CAAA,aAAA,CAAC,aAAa,EAAA,EAAC,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAA,CAAI,CACxD;AAEb,CAAC;AAED,YAAY,CAAC,WAAW,GAAG,cAAc;;;;"}
|