@planningcenter/tapestry 4.2.0-rc.10 → 4.2.0-rc.11

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.
@@ -0,0 +1,52 @@
1
+ import "./btn.css";
2
+ import React from "react";
3
+ import { BaseButtonElementProps } from "./BaseButton";
4
+ type ToggleButtonControlledProps = {
5
+ /** Not available when `pressed` is provided. */
6
+ defaultPressed?: never;
7
+ /** Whether the button is pressed. Maps to `aria-pressed`. */
8
+ pressed: boolean;
9
+ };
10
+ type ToggleButtonUncontrolledProps = {
11
+ /** Initial pressed state. Defaults to `false` if omitted. */
12
+ defaultPressed?: boolean;
13
+ /** Omit to let the button manage its own pressed state. */
14
+ pressed?: never;
15
+ };
16
+ export type ToggleButtonProps = (ToggleButtonControlledProps | ToggleButtonUncontrolledProps) & {
17
+ /** Called with the next pressed state after each click. */
18
+ onChange?: (pressed: boolean) => void;
19
+ };
20
+ export declare function toggleButtonProps({ pressed }: {
21
+ pressed: boolean;
22
+ }): {
23
+ "aria-pressed": boolean;
24
+ };
25
+ /**
26
+ * Resolves `pressed`/`defaultPressed`/`onChange` into a current
27
+ * pressed value and a click handler, whether the caller controls `pressed`
28
+ * or leaves the button to manage it. Always returns a real boolean — a
29
+ * toggle button must always announce `aria-pressed`, even with no props at
30
+ * all — starting from `defaultPressed` (or `false`) when uncontrolled.
31
+ */
32
+ export declare function usePressedState({ defaultPressed, onChange, pressed, }: {
33
+ defaultPressed?: boolean;
34
+ onChange?: (pressed: boolean) => void;
35
+ pressed?: boolean;
36
+ }): [boolean, () => void];
37
+ /**
38
+ * A button that stays either "on" or "off" after each click — Mute,
39
+ * Bookmark, a filter chip — rather than firing a one-time action. Maps
40
+ * `pressed` to the native `aria-pressed` attribute, always present since a
41
+ * toggle button must announce that state. Manages its own pressed state,
42
+ * starting from `false`, when `pressed` is omitted — pass `defaultPressed`
43
+ * and/or `onChange` to seed or observe that uncontrolled state.
44
+ * Carries no default `kind` or CSS; `kind`/`className` stay exactly as
45
+ * caller-controlled as they are on plain `Button`.
46
+ *
47
+ * @component
48
+ * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-button--docs | Storybook Documentation}
49
+ */
50
+ export declare const ToggleButton: React.ForwardRefExoticComponent<(Omit<BaseButtonElementProps, "onChange"> & ToggleButtonProps) & React.RefAttributes<HTMLButtonElement>>;
51
+ export {};
52
+ //# sourceMappingURL=ToggleButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,OAAO,KAA+B,MAAM,OAAO,CAAA;AAEnD,OAAO,EAAc,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAEjE,KAAK,2BAA2B,GAAG;IACjC,gDAAgD;IAChD,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,6DAA6D;IAC7D,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,KAAK,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,CAC5B,2BAA2B,GAC3B,6BAA6B,CAChC,GAAG;IACF,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CACtC,CAAA;AAED,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE;;EAElE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,cAAc,EACd,QAAQ,EACR,OAAO,GACR,EAAE;IACD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,CAmBxB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,0IAkCxB,CAAA"}
@@ -0,0 +1,56 @@
1
+ import React__default, { forwardRef, useState } from 'react';
2
+ import { BaseButton } from './BaseButton.js';
3
+
4
+ function toggleButtonProps({ pressed }) {
5
+ return { "aria-pressed": pressed };
6
+ }
7
+ /**
8
+ * Resolves `pressed`/`defaultPressed`/`onChange` into a current
9
+ * pressed value and a click handler, whether the caller controls `pressed`
10
+ * or leaves the button to manage it. Always returns a real boolean — a
11
+ * toggle button must always announce `aria-pressed`, even with no props at
12
+ * all — starting from `defaultPressed` (or `false`) when uncontrolled.
13
+ */
14
+ function usePressedState({ defaultPressed, onChange, pressed, }) {
15
+ const [uncontrolledPressed, setUncontrolledPressed] = useState(defaultPressed ?? false);
16
+ const isControlled = pressed !== undefined;
17
+ if (isControlled) {
18
+ const toggleControlledPressed = () => onChange?.(!pressed);
19
+ return [pressed, toggleControlledPressed];
20
+ }
21
+ const toggleUncontrolledPressed = () => {
22
+ const nextPressed = !uncontrolledPressed;
23
+ setUncontrolledPressed(nextPressed);
24
+ onChange?.(nextPressed);
25
+ };
26
+ return [uncontrolledPressed, toggleUncontrolledPressed];
27
+ }
28
+ /**
29
+ * A button that stays either "on" or "off" after each click — Mute,
30
+ * Bookmark, a filter chip — rather than firing a one-time action. Maps
31
+ * `pressed` to the native `aria-pressed` attribute, always present since a
32
+ * toggle button must announce that state. Manages its own pressed state,
33
+ * starting from `false`, when `pressed` is omitted — pass `defaultPressed`
34
+ * and/or `onChange` to seed or observe that uncontrolled state.
35
+ * Carries no default `kind` or CSS; `kind`/`className` stay exactly as
36
+ * caller-controlled as they are on plain `Button`.
37
+ *
38
+ * @component
39
+ * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-button--docs | Storybook Documentation}
40
+ */
41
+ const ToggleButton = forwardRef(({ defaultPressed, onClick, onChange, pressed, ...restProps }, ref) => {
42
+ const [currentPressed, togglePressed] = usePressedState({
43
+ defaultPressed,
44
+ onChange,
45
+ pressed,
46
+ });
47
+ const handleClick = (event) => {
48
+ togglePressed();
49
+ onClick?.(event);
50
+ };
51
+ return (React__default.createElement(BaseButton, { ref: ref, ...restProps, onClick: handleClick, ...toggleButtonProps({ pressed: currentPressed }) }));
52
+ });
53
+ ToggleButton.displayName = "ToggleButton";
54
+
55
+ export { ToggleButton, toggleButtonProps, usePressedState };
56
+ //# sourceMappingURL=ToggleButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToggleButton.js","sources":["../../../src/components/button/ToggleButton.tsx"],"sourcesContent":["import \"./btn.css\"\n\nimport React, { forwardRef, useState } from \"react\"\n\nimport { BaseButton, BaseButtonElementProps } from \"./BaseButton\"\n\ntype ToggleButtonControlledProps = {\n /** Not available when `pressed` is provided. */\n defaultPressed?: never\n /** Whether the button is pressed. Maps to `aria-pressed`. */\n pressed: boolean\n}\n\ntype ToggleButtonUncontrolledProps = {\n /** Initial pressed state. Defaults to `false` if omitted. */\n defaultPressed?: boolean\n /** Omit to let the button manage its own pressed state. */\n pressed?: never\n}\n\nexport type ToggleButtonProps = (\n | ToggleButtonControlledProps\n | ToggleButtonUncontrolledProps\n) & {\n /** Called with the next pressed state after each click. */\n onChange?: (pressed: boolean) => void\n}\n\nexport function toggleButtonProps({ pressed }: { pressed: boolean }) {\n return { \"aria-pressed\": pressed }\n}\n\n/**\n * Resolves `pressed`/`defaultPressed`/`onChange` into a current\n * pressed value and a click handler, whether the caller controls `pressed`\n * or leaves the button to manage it. Always returns a real boolean — a\n * toggle button must always announce `aria-pressed`, even with no props at\n * all — starting from `defaultPressed` (or `false`) when uncontrolled.\n */\nexport function usePressedState({\n defaultPressed,\n onChange,\n pressed,\n}: {\n defaultPressed?: boolean\n onChange?: (pressed: boolean) => void\n pressed?: boolean\n}): [boolean, () => void] {\n const [uncontrolledPressed, setUncontrolledPressed] = useState(\n defaultPressed ?? false\n )\n\n const isControlled = pressed !== undefined\n\n if (isControlled) {\n const toggleControlledPressed = () => onChange?.(!pressed)\n return [pressed, toggleControlledPressed]\n }\n\n const toggleUncontrolledPressed = () => {\n const nextPressed = !uncontrolledPressed\n setUncontrolledPressed(nextPressed)\n onChange?.(nextPressed)\n }\n\n return [uncontrolledPressed, toggleUncontrolledPressed]\n}\n\n/**\n * A button that stays either \"on\" or \"off\" after each click — Mute,\n * Bookmark, a filter chip — rather than firing a one-time action. Maps\n * `pressed` to the native `aria-pressed` attribute, always present since a\n * toggle button must announce that state. Manages its own pressed state,\n * starting from `false`, when `pressed` is omitted — pass `defaultPressed`\n * and/or `onChange` to seed or observe that uncontrolled state.\n * Carries no default `kind` or CSS; `kind`/`className` stay exactly as\n * caller-controlled as they are on plain `Button`.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-button--docs | Storybook Documentation}\n */\nexport const ToggleButton = forwardRef<\n HTMLButtonElement,\n Omit<BaseButtonElementProps, \"onChange\"> & ToggleButtonProps\n>(\n (\n {\n defaultPressed,\n onClick,\n onChange,\n pressed,\n ...restProps\n }: Omit<BaseButtonElementProps, \"onChange\"> & ToggleButtonProps,\n ref\n ) => {\n const [currentPressed, togglePressed] = usePressedState({\n defaultPressed,\n onChange,\n pressed,\n })\n\n const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {\n togglePressed()\n onClick?.(event)\n }\n\n return (\n <BaseButton\n ref={ref}\n {...restProps}\n onClick={handleClick}\n {...toggleButtonProps({ pressed: currentPressed })}\n />\n )\n }\n)\n\nToggleButton.displayName = \"ToggleButton\"\n"],"names":["React"],"mappings":";;;AA4BM,SAAU,iBAAiB,CAAC,EAAE,OAAO,EAAwB,EAAA;AACjE,IAAA,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE;AACpC;AAEA;;;;;;AAMG;AACG,SAAU,eAAe,CAAC,EAC9B,cAAc,EACd,QAAQ,EACR,OAAO,GAKR,EAAA;AACC,IAAA,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAC5D,cAAc,IAAI,KAAK,CACxB;AAED,IAAA,MAAM,YAAY,GAAG,OAAO,KAAK,SAAS;IAE1C,IAAI,YAAY,EAAE;QAChB,MAAM,uBAAuB,GAAG,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC;AAC1D,QAAA,OAAO,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC3C;IAEA,MAAM,yBAAyB,GAAG,MAAK;AACrC,QAAA,MAAM,WAAW,GAAG,CAAC,mBAAmB;QACxC,sBAAsB,CAAC,WAAW,CAAC;AACnC,QAAA,QAAQ,GAAG,WAAW,CAAC;AACzB,IAAA,CAAC;AAED,IAAA,OAAO,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;AACzD;AAEA;;;;;;;;;;;;AAYG;MACU,YAAY,GAAG,UAAU,CAIpC,CACE,EACE,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,EACP,GAAG,SAAS,EACiD,EAC/D,GAAG,KACD;AACF,IAAA,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,GAAG,eAAe,CAAC;QACtD,cAAc;QACd,QAAQ;QACR,OAAO;AACR,KAAA,CAAC;AAEF,IAAA,MAAM,WAAW,GAA+C,CAAC,KAAK,KAAI;AACxE,QAAA,aAAa,EAAE;AACf,QAAA,OAAO,GAAG,KAAK,CAAC;AAClB,IAAA,CAAC;IAED,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,GAAG,EAAE,GAAG,EAAA,GACJ,SAAS,EACb,OAAO,EAAE,WAAW,EAAA,GAChB,iBAAiB,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAA,CAClD;AAEN,CAAC;AAGH,YAAY,CAAC,WAAW,GAAG,cAAc;;;;"}
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { IconButtonProps } from "./IconButton";
3
+ import { ToggleButtonProps } from "./ToggleButton";
4
+ /**
5
+ * An icon-only button that stays either "on" or "off" after each click.
6
+ * Maps `pressed` to the native `aria-pressed` attribute, always present
7
+ * since a toggle button must announce that state. Manages its own pressed
8
+ * state, starting from `false`, when `pressed` is omitted — pass
9
+ * `defaultPressed` and/or `onChange` to seed or observe that
10
+ * uncontrolled state. Carries no default `kind` or CSS; `kind`/`className`
11
+ * stay exactly as caller-controlled as they are on plain `IconButton`.
12
+ *
13
+ * @component
14
+ * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-icon-button--docs | Storybook Documentation}
15
+ */
16
+ export declare const ToggleIconButton: React.ForwardRefExoticComponent<(Omit<IconButtonProps, "onChange"> & ToggleButtonProps) & React.RefAttributes<HTMLButtonElement>>;
17
+ //# sourceMappingURL=ToggleIconButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToggleIconButton.d.ts","sourceRoot":"","sources":["../../../src/components/button/ToggleIconButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAA;AAEzC,OAAO,EAAc,eAAe,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,EACL,iBAAiB,EAGlB,MAAM,gBAAgB,CAAA;AAEvB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,mIAkC5B,CAAA"}
@@ -0,0 +1,32 @@
1
+ import React__default, { forwardRef } from 'react';
2
+ import { IconButton } from './IconButton.js';
3
+ import { usePressedState, toggleButtonProps } from './ToggleButton.js';
4
+
5
+ /**
6
+ * An icon-only button that stays either "on" or "off" after each click.
7
+ * Maps `pressed` to the native `aria-pressed` attribute, always present
8
+ * since a toggle button must announce that state. Manages its own pressed
9
+ * state, starting from `false`, when `pressed` is omitted — pass
10
+ * `defaultPressed` and/or `onChange` to seed or observe that
11
+ * uncontrolled state. Carries no default `kind` or CSS; `kind`/`className`
12
+ * stay exactly as caller-controlled as they are on plain `IconButton`.
13
+ *
14
+ * @component
15
+ * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-icon-button--docs | Storybook Documentation}
16
+ */
17
+ const ToggleIconButton = forwardRef(({ defaultPressed, onClick, onChange, pressed, ...restProps }, ref) => {
18
+ const [currentPressed, togglePressed] = usePressedState({
19
+ defaultPressed,
20
+ onChange,
21
+ pressed,
22
+ });
23
+ const handleClick = (event) => {
24
+ togglePressed();
25
+ onClick?.(event);
26
+ };
27
+ return (React__default.createElement(IconButton, { ref: ref, ...restProps, onClick: handleClick, ...toggleButtonProps({ pressed: currentPressed }) }));
28
+ });
29
+ ToggleIconButton.displayName = "ToggleIconButton";
30
+
31
+ export { ToggleIconButton };
32
+ //# sourceMappingURL=ToggleIconButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToggleIconButton.js","sources":["../../../src/components/button/ToggleIconButton.tsx"],"sourcesContent":["import React, { forwardRef } from \"react\"\n\nimport { IconButton, IconButtonProps } from \"./IconButton\"\nimport {\n ToggleButtonProps,\n toggleButtonProps,\n usePressedState,\n} from \"./ToggleButton\"\n\n/**\n * An icon-only button that stays either \"on\" or \"off\" after each click.\n * Maps `pressed` to the native `aria-pressed` attribute, always present\n * since a toggle button must announce that state. Manages its own pressed\n * state, starting from `false`, when `pressed` is omitted — pass\n * `defaultPressed` and/or `onChange` to seed or observe that\n * uncontrolled state. Carries no default `kind` or CSS; `kind`/`className`\n * stay exactly as caller-controlled as they are on plain `IconButton`.\n *\n * @component\n * @see {@link https://planningcenter.github.io/tapestry/?path=/docs/unstable-toggle-icon-button--docs | Storybook Documentation}\n */\nexport const ToggleIconButton = forwardRef<\n HTMLButtonElement,\n Omit<IconButtonProps, \"onChange\"> & ToggleButtonProps\n>(\n (\n {\n defaultPressed,\n onClick,\n onChange,\n pressed,\n ...restProps\n }: Omit<IconButtonProps, \"onChange\"> & ToggleButtonProps,\n ref\n ) => {\n const [currentPressed, togglePressed] = usePressedState({\n defaultPressed,\n onChange,\n pressed,\n })\n\n const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {\n togglePressed()\n onClick?.(event)\n }\n\n return (\n <IconButton\n ref={ref}\n {...restProps}\n onClick={handleClick}\n {...toggleButtonProps({ pressed: currentPressed })}\n />\n )\n }\n)\n\nToggleIconButton.displayName = \"ToggleIconButton\"\n"],"names":["React"],"mappings":";;;;AASA;;;;;;;;;;;AAWG;MACU,gBAAgB,GAAG,UAAU,CAIxC,CACE,EACE,cAAc,EACd,OAAO,EACP,QAAQ,EACR,OAAO,EACP,GAAG,SAAS,EAC0C,EACxD,GAAG,KACD;AACF,IAAA,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,GAAG,eAAe,CAAC;QACtD,cAAc;QACd,QAAQ;QACR,OAAO;AACR,KAAA,CAAC;AAEF,IAAA,MAAM,WAAW,GAA+C,CAAC,KAAK,KAAI;AACxE,QAAA,aAAa,EAAE;AACf,QAAA,OAAO,GAAG,KAAK,CAAC;AAClB,IAAA,CAAC;IAED,QACEA,cAAA,CAAA,aAAA,CAAC,UAAU,EAAA,EACT,GAAG,EAAE,GAAG,EAAA,GACJ,SAAS,EACb,OAAO,EAAE,WAAW,EAAA,GAChB,iBAAiB,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAA,CAClD;AAEN,CAAC;AAGH,gBAAgB,CAAC,WAAW,GAAG,kBAAkB;;;;"}
package/dist/index.css CHANGED
@@ -2303,12 +2303,23 @@ tds-sidenav-section:not(.hydrated) > [slot="ssr"]{
2303
2303
  border-color:var(--tds-btn-border-color-hover);
2304
2304
  }
2305
2305
 
2306
- .tds-btn:active,.tds-btn.active,.tds-btn[aria-pressed="true"]{
2306
+ .tds-btn:active,.tds-btn.active{
2307
2307
  color:var(--tds-btn-color-active);
2308
2308
  background-color:var(--tds-btn-bg-active);
2309
2309
  border-color:var(--tds-btn-border-color-active);
2310
2310
  }
2311
2311
 
2312
+ .tds-btn[aria-pressed="true"]{
2313
+ color:var(--tds-btn-color-active);
2314
+ background-color:var(--tds-btn-bg-active);
2315
+ border-color:var(--tds-btn-border-color-active);
2316
+ }
2317
+
2318
+ .tds-btn[aria-pressed="true"]:hover,.tds-btn[aria-pressed="true"]:focus-visible{
2319
+ background-color:hsl(from var(--tds-btn-bg-active) h s calc(l - 5));
2320
+ border-color:hsl(from var(--tds-btn-border-color-active) h s calc(l - 5));
2321
+ }
2322
+
2312
2323
  .tds-btn:disabled,.tds-btn.disabled{
2313
2324
  --tds-btn-loading-spinner-track-color:var(--t-fill-color-transparency-dark-020);
2314
2325
  --tds-btn-loading-spinner-color:var(--t-text-color-status-neutral);