kang-components 0.5.0 → 0.7.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.
@@ -0,0 +1,51 @@
1
+ /**
2
+ * BackButton — a domain-free "go back" control.
3
+ *
4
+ * Ported from ymy-components (`./buttons/BackButton`), where it was a bare
5
+ * `<IoChevronBackOutline onClick={...} />` with no semantics, no press feedback
6
+ * and no theming. The kang port keeps the same public surface (`size`, `onClick`)
7
+ * but upgrades it into a real, accessible control following kang conventions:
8
+ *
9
+ * - Renders a semantic `<button type="button">` (was a bare SVG with a click
10
+ * handler) so it is keyboard-focusable and announced as a button.
11
+ * - Press feedback via the shared `pressPrimary()` CSS primitive — the same
12
+ * scale/bounce language every kang action button uses.
13
+ * - A Material `Ripple` overlay on press, themed off `theme.colors.ripple`.
14
+ * - Icon color reads `theme.colors.onSurface` (falls back to `currentColor`),
15
+ * so it adapts to a styled-components `ThemeProvider` but still works without
16
+ * one.
17
+ * - `disabled` support: blocks the click and dims the control.
18
+ *
19
+ * Icon: ymy hard-depended on `react-icons` (IoChevronBackOutline). To keep kang
20
+ * dependency-light and domain-free, the same chevron-back glyph ships as an
21
+ * inline SVG (identical Ionicons path data), and consumers may override it with
22
+ * any node via `icon` — the same pattern as BannerButton.
23
+ *
24
+ * `styled-components` and `react` are the only things this module pulls in;
25
+ * consumers importing the press/string primitives never touch them.
26
+ */
27
+ import { type ReactElement, type ReactNode } from 'react';
28
+ export type BackButtonProps = {
29
+ /** Icon size (any CSS size value). Defaults to `'1.5rem'` — matching ymy. */
30
+ size?: string;
31
+ /**
32
+ * Optional click handler, invoked on click/activation. If omitted the button
33
+ * is inert (renders, but does nothing on press).
34
+ */
35
+ onClick?: () => void;
36
+ /** Disable the control: blocks the handler and dims the icon. */
37
+ disabled?: boolean;
38
+ /** Accessible label for screen readers. Defaults to `'Back'`. */
39
+ ariaLabel?: string;
40
+ /** Optional class name passthrough for layout/positioning by the consumer. */
41
+ className?: string;
42
+ /**
43
+ * An explicit icon node, overriding the default inline chevron. Lets
44
+ * consumers supply their own glyph (e.g. a react-icons element) without kang
45
+ * depending on an icon library.
46
+ */
47
+ icon?: ReactNode;
48
+ };
49
+ declare const BackButton: ({ size, onClick, disabled, ariaLabel, className, icon, }: BackButtonProps) => ReactElement;
50
+ export default BackButton;
51
+ //# sourceMappingURL=back-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"back-button.d.ts","sourceRoot":"","sources":["../src/back-button.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAgC,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAKxF,MAAM,MAAM,eAAe,GAAG;IAC7B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC;AAoDF,QAAA,MAAM,UAAU,6DAOb,eAAe,KAAG,YAyBpB,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * BackButton — a domain-free "go back" control.
4
+ *
5
+ * Ported from ymy-components (`./buttons/BackButton`), where it was a bare
6
+ * `<IoChevronBackOutline onClick={...} />` with no semantics, no press feedback
7
+ * and no theming. The kang port keeps the same public surface (`size`, `onClick`)
8
+ * but upgrades it into a real, accessible control following kang conventions:
9
+ *
10
+ * - Renders a semantic `<button type="button">` (was a bare SVG with a click
11
+ * handler) so it is keyboard-focusable and announced as a button.
12
+ * - Press feedback via the shared `pressPrimary()` CSS primitive — the same
13
+ * scale/bounce language every kang action button uses.
14
+ * - A Material `Ripple` overlay on press, themed off `theme.colors.ripple`.
15
+ * - Icon color reads `theme.colors.onSurface` (falls back to `currentColor`),
16
+ * so it adapts to a styled-components `ThemeProvider` but still works without
17
+ * one.
18
+ * - `disabled` support: blocks the click and dims the control.
19
+ *
20
+ * Icon: ymy hard-depended on `react-icons` (IoChevronBackOutline). To keep kang
21
+ * dependency-light and domain-free, the same chevron-back glyph ships as an
22
+ * inline SVG (identical Ionicons path data), and consumers may override it with
23
+ * any node via `icon` — the same pattern as BannerButton.
24
+ *
25
+ * `styled-components` and `react` are the only things this module pulls in;
26
+ * consumers importing the press/string primitives never touch them.
27
+ */
28
+ import { useCallback } from 'react';
29
+ import { styled } from 'styled-components';
30
+ import { pressPrimary } from './press.js';
31
+ import { Ripple, useRipple } from './ripple.js';
32
+ /**
33
+ * Inline IoChevronBackOutline (react-icons/io5) — identical Ionicons path data
34
+ * (viewBox + stroke-width 48 outline chevron) so the glyph is unchanged.
35
+ */
36
+ const ChevronBackIcon = ({ size }) => (_jsx("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 512 512", height: size, width: size, xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: _jsx("path", { fill: "none", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "48", d: "M328 112 184 256l144 144" }) }));
37
+ const StyledBackButton = styled.button `
38
+ position: relative;
39
+ overflow: hidden;
40
+ display: inline-flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ padding: 0;
44
+ margin: 0;
45
+ border: none;
46
+ background: transparent;
47
+ cursor: ${({ $disabled }) => ($disabled ? 'not-allowed' : 'pointer')};
48
+ color: ${({ theme }) => theme?.colors?.onSurface ?? 'currentColor'};
49
+ opacity: ${({ $disabled }) => ($disabled ? 0.4 : 1)};
50
+ line-height: 0;
51
+ -webkit-tap-highlight-color: transparent;
52
+
53
+ ${pressPrimary()}
54
+
55
+ &:disabled {
56
+ pointer-events: none;
57
+ }
58
+ `;
59
+ const BackButton = ({ size, onClick, disabled = false, ariaLabel = 'Back', className, icon, }) => {
60
+ const { ripple, trigger, isTarget } = useRipple();
61
+ const handleClick = useCallback((e) => {
62
+ if (disabled)
63
+ return;
64
+ trigger(e, 'back');
65
+ onClick?.();
66
+ }, [disabled, onClick, trigger]);
67
+ return (_jsxs(StyledBackButton, { type: "button", className: className, "$disabled": disabled, disabled: disabled, "aria-label": ariaLabel, onClick: handleClick, children: [icon !== undefined ? icon : _jsx(ChevronBackIcon, { size: size != null ? size : '1.5rem' }), isTarget('back') && ripple && _jsx(Ripple, { "$x": ripple.x, "$y": ripple.y }, ripple.key)] }));
68
+ };
69
+ export default BackButton;
70
+ //# sourceMappingURL=back-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"back-button.js","sourceRoot":"","sources":["../src/back-button.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,WAAW,EAAsD,MAAM,OAAO,CAAC;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAwBhD;;;GAGG;AACH,MAAM,eAAe,GAAG,CAAC,EAAE,IAAI,EAAoB,EAAgB,EAAE,CAAC,CACrE,cACC,MAAM,EAAC,cAAc,EACrB,IAAI,EAAC,cAAc,EACnB,WAAW,EAAC,GAAG,EACf,OAAO,EAAC,aAAa,EACrB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,KAAK,EAAC,4BAA4B,iBACtB,MAAM,EAClB,SAAS,EAAC,OAAO,YAEjB,eACC,IAAI,EAAC,MAAM,EACX,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAC,IAAI,EAChB,CAAC,EAAC,0BAA0B,GAC3B,GACG,CACN,CAAC;AAEF,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAwB;;;;;;;;;;WAUnD,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;UAC3D,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACrB,KAA6C,EAAE,MAAM,EAAE,SAAS,IAAI,cAAc;YACzE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;;;;GAIjD,YAAY,EAAE;;;;;CAKhB,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,EACnB,IAAI,EACJ,OAAO,EACP,QAAQ,GAAG,KAAK,EAChB,SAAS,GAAG,MAAM,EAClB,SAAS,EACT,IAAI,GACa,EAAgB,EAAE;IACnC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,SAAS,EAAU,CAAC;IAE1D,MAAM,WAAW,GAAG,WAAW,CAC9B,CAAC,CAAgC,EAAE,EAAE;QACpC,IAAI,QAAQ;YAAE,OAAO;QACrB,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QACnB,OAAO,EAAE,EAAE,CAAC;IACb,CAAC,EACD,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAC5B,CAAC;IAEF,OAAO,CACN,MAAC,gBAAgB,IAChB,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,SAAS,eACT,QAAQ,EACnB,QAAQ,EAAE,QAAQ,gBACN,SAAS,EACrB,OAAO,EAAE,WAAW,aAEnB,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,eAAe,IAAC,IAAI,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAI,EACrF,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,KAAC,MAAM,UAAsB,MAAM,CAAC,CAAC,QAAM,MAAM,CAAC,CAAC,IAAtC,MAAM,CAAC,GAAG,CAAgC,IACpE,CACnB,CAAC;AACH,CAAC,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Badge — a domain-free pill that displays a prominent value with an optional
3
+ * label, in one of a few visual variants.
4
+ *
5
+ * Ported from ymy-components (`./badge/Badge`), where it lived as a 3-file unit
6
+ * (`Badge.tsx` + `Badge.types.ts` + `Badge.styles.ts`) and shipped untested.
7
+ * The kang port collapses it into a single flat-ESM module and preserves the
8
+ * public API exactly (`value`, `label`, `variant`), so xunzi's re-point site
9
+ * (`StreakBadge.tsx`) is a pure import swap.
10
+ *
11
+ * Theming follows kang conventions: every color reads a styled-components
12
+ * `theme.colors.*` token with a literal fallback, so the badge adapts to a
13
+ * `ThemeProvider` (light/dark) yet still renders sensibly without one. The ymy
14
+ * source hardcoded the `success` variant's green; the kang port routes it
15
+ * through the theme's `successContainer`/`successDark` tokens (same literal
16
+ * fallbacks) so it matches mode like every other variant.
17
+ *
18
+ * `styled-components` and `react` are the only things this module pulls in.
19
+ */
20
+ import { type ReactElement, type ReactNode } from 'react';
21
+ export type BadgeVariant = 'primary' | 'muted' | 'success';
22
+ export interface BadgeProps {
23
+ /** The primary value displayed prominently. */
24
+ value: ReactNode;
25
+ /** Optional label displayed next to the value (rendered uppercase). */
26
+ label?: string;
27
+ /** Visual variant (default: `'primary'`). */
28
+ variant?: BadgeVariant;
29
+ /** Optional class name passthrough for layout/positioning by the consumer. */
30
+ className?: string;
31
+ }
32
+ export declare function Badge({ value, label, variant, className, }: BadgeProps): ReactElement;
33
+ export default Badge;
34
+ //# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG1D,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,UAAU;IAC1B,+CAA+C;IAC/C,KAAK,EAAE,SAAS,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAiDD,wBAAgB,KAAK,CAAC,EACrB,KAAK,EACL,KAAK,EACL,OAAmB,EACnB,SAAS,GACT,EAAE,UAAU,GAAG,YAAY,CAO3B;AAED,eAAe,KAAK,CAAC"}
package/dist/badge.js ADDED
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { styled, css } from 'styled-components';
3
+ const containerVariant = {
4
+ primary: css `
5
+ background: ${({ theme }) => theme?.colors?.whiteLow ?? 'rgba(255, 255, 255, 0.2)'};
6
+ `,
7
+ muted: css `
8
+ background: ${({ theme }) => theme?.colors?.surfaceVariant ?? 'rgba(0, 0, 0, 0.06)'};
9
+ `,
10
+ success: css `
11
+ background: ${({ theme }) => theme?.colors?.successContainer ?? 'rgba(34, 197, 94, 0.15)'};
12
+ `,
13
+ };
14
+ const BadgeContainer = styled.div `
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ gap: 0.25rem;
19
+ padding: 0.75rem 1rem;
20
+ border-radius: 1rem;
21
+ min-width: 4rem;
22
+ ${({ $variant }) => containerVariant[$variant]}
23
+ `;
24
+ const BadgeValue = styled.span `
25
+ font-size: 1.25rem;
26
+ font-weight: 600;
27
+ line-height: 1;
28
+ color: ${({ $variant, theme }) => {
29
+ const colors = theme?.colors;
30
+ if ($variant === 'success')
31
+ return colors?.successDark ?? '#16a34a';
32
+ return colors?.primaryDarker ?? colors?.primary ?? '#333';
33
+ }};
34
+ `;
35
+ const BadgeLabel = styled.span `
36
+ font-size: 0.625rem;
37
+ font-weight: 500;
38
+ color: ${({ theme }) => theme?.colors?.onSurface ?? '#333'};
39
+ text-transform: uppercase;
40
+ letter-spacing: 0.05em;
41
+ `;
42
+ export function Badge({ value, label, variant = 'primary', className, }) {
43
+ return (_jsxs(BadgeContainer, { "$variant": variant, className: className, children: [_jsx(BadgeValue, { "$variant": variant, children: value }), label && _jsx(BadgeLabel, { children: label })] }));
44
+ }
45
+ export default Badge;
46
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../src/badge.tsx"],"names":[],"mappings":";AAqBA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAiBhD,MAAM,gBAAgB,GAAG;IACxB,OAAO,EAAE,GAAG,CAAA;gBACG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAC1B,KAAqB,EAAE,MAAM,EAAE,QAAQ,IAAI,0BAA0B;EACvE;IACD,KAAK,EAAE,GAAG,CAAA;gBACK,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAC1B,KAAqB,EAAE,MAAM,EAAE,cAAc,IAAI,qBAAqB;EACxE;IACD,OAAO,EAAE,GAAG,CAAA;gBACG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAC1B,KAAqB,EAAE,MAAM,EAAE,gBAAgB,IAAI,yBAAyB;EAC9E;CACD,CAAC;AAEF,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAA4B;;;;;;;;GAQ1D,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC;CAC9C,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAA4B;;;;UAIhD,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE;IAChC,MAAM,MAAM,GAAI,KAAqB,EAAE,MAAM,CAAC;IAC9C,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,EAAE,WAAW,IAAI,SAAS,CAAC;IACpE,OAAO,MAAM,EAAE,aAAa,IAAI,MAAM,EAAE,OAAO,IAAI,MAAM,CAAC;AAC3D,CAAC;CACD,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;;;UAGpB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAE,KAAqB,EAAE,MAAM,EAAE,SAAS,IAAI,MAAM;;;CAG3E,CAAC;AAEF,MAAM,UAAU,KAAK,CAAC,EACrB,KAAK,EACL,KAAK,EACL,OAAO,GAAG,SAAS,EACnB,SAAS,GACG;IACZ,OAAO,CACN,MAAC,cAAc,gBAAW,OAAO,EAAE,SAAS,EAAE,SAAS,aACtD,KAAC,UAAU,gBAAW,OAAO,YAAG,KAAK,GAAc,EAClD,KAAK,IAAI,KAAC,UAAU,cAAE,KAAK,GAAc,IAC1B,CACjB,CAAC;AACH,CAAC;AAED,eAAe,KAAK,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * BannerButton — a pill-shaped call-to-action button with a leading icon and
3
+ * cross-fading multilingual label.
4
+ *
5
+ * Ported from ymy-components (`./buttons/BannerButton`). The visual language is
6
+ * preserved (rounded pill, drop shadow, primary/secondary variants, a press
7
+ * "scale-down" feedback) but reconciled onto kang's conventions:
8
+ *
9
+ * - **Theme-driven colors** read off styled-components' `props.theme` (the same
10
+ * tokens {@link buildTheme} produces), with literal fallbacks so the button
11
+ * still renders without a `ThemeProvider`.
12
+ * - **Press feedback** uses kang's CSS-first {@link pressPrimary} primitive
13
+ * instead of a bespoke keyframe, keeping the press language consistent across
14
+ * the library.
15
+ * - **Label** delegates to kang's domain-free {@link AnimatedText}: the
16
+ * multilingual `buttonText` is mapped to `variants` (english ↔ preferred
17
+ * Chinese set) with all three strings reserved as sizers so the box never
18
+ * reflows mid-swap.
19
+ *
20
+ * Icons: ymy hard-depended on `react-icons` (FaPlus / FiSend). To keep kang
21
+ * dependency-light and domain-free, the same two glyphs ship as inline SVGs
22
+ * selectable via `iconComponent`, and consumers may pass any node via `icon`.
23
+ *
24
+ * `styled-components` and `react` are optional peer dependencies, pulled in only
25
+ * by this (and other runtime) modules.
26
+ */
27
+ import { type ReactNode } from 'react';
28
+ import type { CharacterPreference, DynamicLanguage } from './language.js';
29
+ export type BannerButtonProps = {
30
+ /**
31
+ * Which built-in icon to display. `'plus'` and `'send'` ship as inline SVGs.
32
+ * Ignored when an explicit `icon` node is provided.
33
+ */
34
+ iconComponent?: 'plus' | 'send';
35
+ /**
36
+ * An explicit icon node, overriding `iconComponent`. Lets consumers supply
37
+ * their own glyph (e.g. a react-icons element) without kang depending on an
38
+ * icon library.
39
+ */
40
+ icon?: ReactNode;
41
+ /** The button label, available in english / traditional / simplified. */
42
+ buttonText: DynamicLanguage;
43
+ /** Visual variant. Defaults to `'primary'`. */
44
+ buttonType?: 'primary' | 'secondary';
45
+ /** Click handler. */
46
+ onClick?: () => void;
47
+ /** Preferred Chinese character set for the label. Defaults to `'simplified'`. */
48
+ characterPreference?: CharacterPreference;
49
+ /** Whether the label cross-fades between english and Chinese. Defaults to true. */
50
+ animate?: boolean;
51
+ };
52
+ export default function BannerButton({ iconComponent, icon, buttonText, buttonType, onClick, characterPreference, animate, }: BannerButtonProps): import("react").JSX.Element;
53
+ //# sourceMappingURL=banner-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner-button.d.ts","sourceRoot":"","sources":["../src/banner-button.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,MAAM,iBAAiB,GAAG;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,yEAAyE;IACzE,UAAU,EAAE,eAAe,CAAC;IAC5B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;IACrC,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,mFAAmF;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AA+FF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACpC,aAAa,EACb,IAAI,EACJ,UAAU,EACV,UAAsB,EACtB,OAAO,EACP,mBAAkC,EAClC,OAAc,GACd,EAAE,iBAAiB,+BAwBnB"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Named imports (not the default) so this resolves consistently across bundler
3
+ // and raw ESM/CJS environments — see the note in ripple.ts.
4
+ import { styled } from 'styled-components';
5
+ import AnimatedText from './animated-text.js';
6
+ import { pressPrimary } from './press.js';
7
+ const BannerButtonContainer = styled.div `
8
+ display: inline-block;
9
+ position: relative;
10
+ overflow: hidden;
11
+ border-radius: 2.5rem;
12
+ background: ${({ theme }) => theme?.colors?.primary ?? '#489fb5'};
13
+ box-shadow: 0px 4px 4px 0px
14
+ ${({ theme }) => theme?.colors?.shadow ?? 'rgba(0, 0, 0, 0.25)'};
15
+
16
+ ${pressPrimary()}
17
+ `;
18
+ const StyledButton = styled.button `
19
+ display: flex;
20
+ align-items: center;
21
+ position: relative;
22
+ z-index: 10;
23
+ padding: 0.5rem 1rem;
24
+ border: none;
25
+ outline: none;
26
+ cursor: pointer;
27
+ transition: background-color 0.3s;
28
+
29
+ &.primary {
30
+ background-color: ${({ theme }) => theme?.colors?.primary ?? '#489fb5'};
31
+ color: ${({ theme }) => theme?.colors?.onPrimary ?? 'white'};
32
+ }
33
+
34
+ &.secondary {
35
+ background-color: ${({ theme }) => theme?.colors?.secondaryLight ?? '#ffb652'};
36
+ color: ${({ theme }) => theme?.colors?.onSecondary ?? 'black'};
37
+ }
38
+ `;
39
+ const IconContainer = styled.span `
40
+ display: flex;
41
+ margin-right: 1.25rem;
42
+
43
+ @media (min-width: 640px) {
44
+ margin-right: 0.25rem;
45
+ }
46
+ `;
47
+ /** Inline FaPlus (react-icons/fa) — kept identical so the glyph is unchanged. */
48
+ const PlusIcon = () => (_jsx("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 448 512", height: "1em", width: "1em", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z" }) }));
49
+ /** Inline FiSend (react-icons/fi) — kept identical so the glyph is unchanged. */
50
+ const SendIcon = () => (_jsxs("svg", { stroke: "currentColor", fill: "none", strokeWidth: "2", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round", height: "1em", width: "1em", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: [_jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }), _jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })] }));
51
+ function resolveIcon(icon, iconComponent) {
52
+ if (icon !== undefined)
53
+ return icon;
54
+ if (iconComponent === 'plus')
55
+ return _jsx(PlusIcon, {});
56
+ if (iconComponent === 'send')
57
+ return _jsx(SendIcon, {});
58
+ return null;
59
+ }
60
+ export default function BannerButton({ iconComponent, icon, buttonText, buttonType = 'primary', onClick, characterPreference = 'simplified', animate = true, }) {
61
+ const iconElement = resolveIcon(icon, iconComponent);
62
+ // Map the multilingual label onto AnimatedText's domain-free variant model:
63
+ // cycle english <-> the preferred Chinese set, static index 0 = english
64
+ // (matching ymy's default). All three strings are reserved as sizers so the
65
+ // box is always sized to the widest and never reflows mid-swap.
66
+ const chineseText = characterPreference === 'traditional' ? buttonText.traditional : buttonText.simplified;
67
+ return (_jsx(BannerButtonContainer, { onClick: onClick, children: _jsxs(StyledButton, { type: "button", className: buttonType, children: [iconElement !== null && _jsx(IconContainer, { children: iconElement }), _jsx(AnimatedText, { textStyles: { lineHeight: '0.8rem', minWidth: '3rem' }, variants: [buttonText.english, chineseText], sizers: [buttonText.english, buttonText.simplified, buttonText.traditional], staticIndex: 0, animate: animate })] }) }));
68
+ }
69
+ //# sourceMappingURL=banner-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner-button.js","sourceRoot":"","sources":["../src/banner-button.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * CircleIconButton — a round, themed icon button with a spring entry animation.
3
+ *
4
+ * Ported faithfully from ymy-components (`./buttons/CircleIconButton`). It renders
5
+ * one of a small set of built-in icons (`person`, `qr`) inside a circular outlined
6
+ * button that scales/fades in on mount via react-spring, and fires `onClick` when
7
+ * pressed. The two xunzi sites that consume it (HeroBanner, ProfileButton) drive it
8
+ * purely through the `iconComponent` string + `onClick`, so that API is preserved
9
+ * 1:1 to keep the re-point a pure import swap.
10
+ *
11
+ * Theming: the border reads `theme.colors.onPrimary` and the icon reads
12
+ * `theme.colors.onSurface` off styled-components' `props.theme`, with literal
13
+ * fallbacks so it renders sensibly with or without a `ThemeProvider`.
14
+ *
15
+ * Press feedback: layered on top of ymy's behavior using kang's `pressPrimary`
16
+ * (the icon-button tier). The entry animation owns `transform` via react-spring,
17
+ * so press uses the CSS `scale` property (`pressPrimaryScale`) to avoid fighting it.
18
+ *
19
+ * Icons: ymy hard-depended on `react-icons` (BsPerson / BsQrCodeScan). To keep
20
+ * kang dependency-light and domain-free, the same two glyphs ship as inline SVGs
21
+ * (matching Bootstrap-icons path data) selectable via `iconComponent`, and
22
+ * consumers may pass any node via `icon` — the same pattern as BannerButton.
23
+ *
24
+ * `styled-components` and `@react-spring/web` are optional peer dependencies, used
25
+ * only by this module — consumers importing just the string primitives never pull
26
+ * them in.
27
+ */
28
+ import { type ReactElement, type ReactNode } from 'react';
29
+ /** The built-in icon set this button can render. */
30
+ export type CircleIconName = 'person' | 'qr';
31
+ export type CircleIconButtonProps = {
32
+ /**
33
+ * Which built-in icon to render. Ignored when an explicit `icon` node is
34
+ * provided.
35
+ * - `'person'` — person icon (profile).
36
+ * - `'qr'` — QR-code scan icon (invite/friend).
37
+ */
38
+ iconComponent: CircleIconName;
39
+ /**
40
+ * An explicit icon node, overriding `iconComponent`. Lets consumers supply
41
+ * their own glyph (e.g. a react-icons element) without kang depending on an
42
+ * icon library — the same override pattern as BannerButton.
43
+ */
44
+ icon?: ReactNode;
45
+ /**
46
+ * Optional click handler, invoked when the button is pressed. If omitted the
47
+ * button still renders and is interactive but performs no action.
48
+ */
49
+ onClick?: () => void;
50
+ };
51
+ export default function CircleIconButton({ iconComponent, icon, onClick, }: CircleIconButtonProps): ReactElement;
52
+ //# sourceMappingURL=circle-icon-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circle-icon-button.d.ts","sourceRoot":"","sources":["../src/circle-icon-button.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAO1D,oDAAoD;AACpD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,IAAI,CAAC;AAE7C,MAAM,MAAM,qBAAqB,GAAG;IACnC;;;;;OAKG;IACH,aAAa,EAAE,cAAc,CAAC;IAE9B;;;;OAIG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAyEF,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACxC,aAAa,EACb,IAAI,EACJ,OAAO,GACP,EAAE,qBAAqB,GAAG,YAAY,CAqBtC"}
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { animated, useSpring } from '@react-spring/web';
3
+ // Named import (not the default) so styled-components resolves consistently
4
+ // across bundler and raw ESM/CJS environments — matches ripple.ts.
5
+ import { styled } from 'styled-components';
6
+ import { pressPrimaryScale } from './press.js';
7
+ const StyledCircleButton = styled(animated.button) `
8
+ width: 2.5rem;
9
+ height: 2.5rem;
10
+ padding: 0;
11
+ border-radius: 50%;
12
+ border: 1px solid
13
+ ${({ theme }) => theme?.colors?.onPrimary ?? 'white'};
14
+ background: transparent;
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ cursor: pointer;
19
+ ${pressPrimaryScale()}
20
+ `;
21
+ const StyledIcon = styled.span `
22
+ display: flex;
23
+ color: ${({ theme }) => theme?.colors?.onSurface ?? 'black'};
24
+ font-size: 1.125rem;
25
+ `;
26
+ /** Inline BsPerson (react-icons/bs) — Bootstrap-icons path data, glyph unchanged. */
27
+ const PersonIcon = () => (_jsx("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 16 16", height: "1em", width: "1em", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: _jsx("path", { d: "M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6m2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0m4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4m-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10s-3.516.68-4.168 1.332c-.678.678-.83 1.418-.832 1.664z" }) }));
28
+ /** Inline BsQrCodeScan (react-icons/bs) — Bootstrap-icons path data, glyph unchanged. */
29
+ const QrIcon = () => (_jsxs("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 16 16", height: "1em", width: "1em", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: [_jsx("path", { d: "M0 .5A.5.5 0 0 1 .5 0h3a.5.5 0 0 1 0 1H1v2.5a.5.5 0 0 1-1 0zm12 0a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0V1h-2.5a.5.5 0 0 1-.5-.5M.5 12a.5.5 0 0 1 .5.5V15h2.5a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5v-3a.5.5 0 0 1 .5-.5m15 0a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1 0-1H15v-2.5a.5.5 0 0 1 .5-.5M4 4h1v1H4z" }), _jsx("path", { d: "M7 2H2v5h5zM3 3h3v3H3zm2 8H4v1h1z" }), _jsx("path", { d: "M7 9H2v5h5zm-4 1h3v3H3zm8-6h1v1h-1z" }), _jsx("path", { d: "M9 2h5v5H9zm1 1v3h3V3zM8 8v2h1v1H8v1h2v-2h1v2h1v-1h2v-1h-3V8zm2 2H9V9h1zm4 2h-1v1h-2v1h3zm-4 2v-1H8v1z" }), _jsx("path", { d: "M12 9h2V8h-2z" })] }));
30
+ const ICONS = {
31
+ person: _jsx(PersonIcon, {}),
32
+ qr: _jsx(QrIcon, {}),
33
+ };
34
+ function resolveIcon(icon, iconComponent) {
35
+ if (icon !== undefined)
36
+ return icon;
37
+ return ICONS[iconComponent];
38
+ }
39
+ export default function CircleIconButton({ iconComponent, icon, onClick, }) {
40
+ const animatedStyles = useSpring({
41
+ from: { opacity: 0, scale: 0.5 },
42
+ to: { opacity: 1, scale: 1 },
43
+ });
44
+ const handleClick = () => {
45
+ if (onClick) {
46
+ onClick();
47
+ }
48
+ };
49
+ return (_jsx(StyledCircleButton, { type: "button", style: animatedStyles, onClick: handleClick, children: _jsx(StyledIcon, { children: resolveIcon(icon, iconComponent) }) }));
50
+ }
51
+ //# sourceMappingURL=circle-icon-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circle-icon-button.js","sourceRoot":"","sources":["../src/circle-icon-button.tsx"],"names":[],"mappings":";AA6BA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACxD,4EAA4E;AAC5E,mEAAmE;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA8B/C,MAAM,kBAAkB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;;;;;;IAM9C,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAE,KAAqB,EAAE,MAAM,EAAE,SAAS,IAAI,OAAO;;;;;;GAMpE,iBAAiB,EAAE;CACrB,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAA;;UAEpB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAE,KAAqB,EAAE,MAAM,EAAE,SAAS,IAAI,OAAO;;CAE5E,CAAC;AAEF,qFAAqF;AACrF,MAAM,UAAU,GAAG,GAAiB,EAAE,CAAC,CACtC,cACC,MAAM,EAAC,cAAc,EACrB,IAAI,EAAC,cAAc,EACnB,WAAW,EAAC,GAAG,EACf,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,KAAK,EACZ,KAAK,EAAC,KAAK,EACX,KAAK,EAAC,4BAA4B,iBACtB,MAAM,EAClB,SAAS,EAAC,OAAO,YAEjB,eAAM,CAAC,EAAC,uOAAuO,GAAG,GAC7O,CACN,CAAC;AAEF,yFAAyF;AACzF,MAAM,MAAM,GAAG,GAAiB,EAAE,CAAC,CAClC,eACC,MAAM,EAAC,cAAc,EACrB,IAAI,EAAC,cAAc,EACnB,WAAW,EAAC,GAAG,EACf,OAAO,EAAC,WAAW,EACnB,MAAM,EAAC,KAAK,EACZ,KAAK,EAAC,KAAK,EACX,KAAK,EAAC,4BAA4B,iBACtB,MAAM,EAClB,SAAS,EAAC,OAAO,aAEjB,eAAM,CAAC,EAAC,gUAAgU,GAAG,EAC3U,eAAM,CAAC,EAAC,mCAAmC,GAAG,EAC9C,eAAM,CAAC,EAAC,qCAAqC,GAAG,EAChD,eAAM,CAAC,EAAC,wGAAwG,GAAG,EACnH,eAAM,CAAC,EAAC,eAAe,GAAG,IACrB,CACN,CAAC;AAEF,MAAM,KAAK,GAAyC;IACnD,MAAM,EAAE,KAAC,UAAU,KAAG;IACtB,EAAE,EAAE,KAAC,MAAM,KAAG;CACd,CAAC;AAEF,SAAS,WAAW,CAAC,IAAe,EAAE,aAA6B;IAClE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACxC,aAAa,EACb,IAAI,EACJ,OAAO,GACgB;IACvB,MAAM,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE;QAChC,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;KAC5B,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,GAAG,EAAE;QACxB,IAAI,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;QACX,CAAC;IACF,CAAC,CAAC;IAEF,OAAO,CACN,KAAC,kBAAkB,IAClB,IAAI,EAAC,QAAQ,EACb,KAAK,EAAE,cAAc,EACrB,OAAO,EAAE,WAAW,YAEpB,KAAC,UAAU,cAAE,WAAW,CAAC,IAAI,EAAE,aAAa,CAAC,GAAc,GACvC,CACrB,CAAC;AACH,CAAC"}
package/dist/index.d.ts CHANGED
@@ -7,9 +7,21 @@ export { SPRING_COMFORTABLE, SPRING_COMFORTABLE_SLOW, SPRING_SNAPPY, SPRING_RESP
7
7
  export type { SpringConfigConstant } from './spring.js';
8
8
  export { default as AnimatedText } from './animated-text.js';
9
9
  export type { AnimatedTextProps } from './animated-text.js';
10
+ export { default as BackButton } from './back-button.js';
11
+ export type { BackButtonProps } from './back-button.js';
12
+ export { default as CircleIconButton } from './circle-icon-button.js';
13
+ export type { CircleIconButtonProps, CircleIconName } from './circle-icon-button.js';
14
+ export { default as BannerButton } from './banner-button.js';
15
+ export type { BannerButtonProps } from './banner-button.js';
16
+ export { Badge } from './badge.js';
17
+ export type { BadgeProps, BadgeVariant } from './badge.js';
18
+ export { default as ToggleSwitch } from './toggle-switch.js';
19
+ export type { ToggleSwitchProps } from './toggle-switch.js';
10
20
  export { buildTheme, theme, hexToRgb } from './theme.js';
11
21
  export type { ThemeType } from './theme.js';
12
22
  export { lightPalette, darkPalette } from './palettes.js';
13
23
  export type { ModeColorPalette } from './palettes.js';
14
24
  export type { DynamicLanguage, CharacterPreference, StaticLanguage, } from './language.js';
25
+ export { ListItem, UnorderedListItemContainer } from './list-item.js';
26
+ export type { ListItemProps, ListItemIconName, ListItemActionName, } from './list-item.js';
15
27
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,cAAc,GACd,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AACtE,YAAY,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACrF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACzD,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,YAAY,EACX,eAAe,EACf,mBAAmB,EACnB,cAAc,GACd,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACtE,YAAY,EACX,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GAClB,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -4,6 +4,12 @@ export { actionSheetContainer, actionSheetList, actionSheetRow, } from './action
4
4
  export { Ripple, rippleAnimation, useRipple } from './ripple.js';
5
5
  export { SPRING_COMFORTABLE, SPRING_COMFORTABLE_SLOW, SPRING_SNAPPY, SPRING_RESPONSIVE, SPRING_STAGGERED, SPRING_INSTANT, SPRING_GENTLE, SPRING_VERY_SLOW, SPRING_LANDING, SPRING_RISING, } from './spring.js';
6
6
  export { default as AnimatedText } from './animated-text.js';
7
+ export { default as BackButton } from './back-button.js';
8
+ export { default as CircleIconButton } from './circle-icon-button.js';
9
+ export { default as BannerButton } from './banner-button.js';
10
+ export { Badge } from './badge.js';
11
+ export { default as ToggleSwitch } from './toggle-switch.js';
7
12
  export { buildTheme, theme, hexToRgb } from './theme.js';
8
13
  export { lightPalette, darkPalette } from './palettes.js';
14
+ export { ListItem, UnorderedListItemContainer } from './list-item.js';
9
15
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,gBAAgB,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,OAAO,EACN,oBAAoB,EACpB,eAAe,EACf,cAAc,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGjE,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,aAAa,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAS1D,OAAO,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * ListItem + UnorderedListItemContainer — a pressable settings/menu row and its
3
+ * list wrapper.
4
+ *
5
+ * Ported from ymy-components (`./collections/ListItem` + `./collections/
6
+ * ListItem.styles`), preserving the exact public API the xunzi call sites
7
+ * (`AuthSection`, `Profile`) drive, so re-pointing them at kang is a pure import
8
+ * swap. A row renders a leading icon, a label, and a trailing action (a chevron,
9
+ * or an inline Material toggle when `actionIcon === 'switch'`), with a Material
10
+ * ripple on press.
11
+ *
12
+ * kang-specific upgrades / adaptations:
13
+ * - **Press feedback** uses kang's shared `Ripple` / `useRipple` primitives
14
+ * (themed off `theme.colors.ripple`), replacing ymy's bespoke ripple wiring.
15
+ * - **Icons:** ymy hard-depended on `react-icons` (MdTranslate / MdOutlineWbSunny
16
+ * / MdChevronRight). To keep kang dependency-light and domain-free, the same
17
+ * glyphs ship as inline SVGs (identical Material-icons path data), selectable
18
+ * via the `icon` string. Consumers may override the leading glyph with any node
19
+ * via `iconNode` — the same override pattern as BackButton / CircleIconButton.
20
+ * - **Text:** the `textContent` path maps the app's `DynamicLanguage` model onto
21
+ * kang's domain-free `AnimatedText` (`variants` / `staticIndex` / `sizers`),
22
+ * exactly as xunzi's AnimatedText adapter does — so language knowledge stays in
23
+ * the shared language types and the motion stays in `AnimatedText`.
24
+ * - **Toggle:** ymy rendered a separate `ToggleSwitch`; that Material toggle is
25
+ * inlined (controlled or uncontrolled) so kang needn't ship a ToggleSwitch yet.
26
+ *
27
+ * `styled-components`, `@react-spring/web` (via AnimatedText) and `react` are the
28
+ * only things this module pulls in, all optional peer deps.
29
+ */
30
+ import { type CSSProperties, type ReactElement, type ReactNode } from 'react';
31
+ import type { CharacterPreference, DynamicLanguage, StaticLanguage } from './language.js';
32
+ /** The built-in leading icons a row can render (was ymy's `PrimaryIcons`). */
33
+ export type ListItemIconName = 'translate' | 'sunny' | 'character';
34
+ /** The built-in trailing actions a row can render (was ymy's `SecondaryIconName`). */
35
+ export type ListItemActionName = 'chevron' | 'switch';
36
+ export type ListItemProps = {
37
+ /** Which built-in leading icon to render. Ignored when `iconNode` is provided. */
38
+ icon: ListItemIconName;
39
+ /**
40
+ * An explicit leading-icon node, overriding the built-in `icon`. Lets
41
+ * consumers supply their own glyph without kang depending on an icon library —
42
+ * the same override pattern as BackButton / CircleIconButton.
43
+ */
44
+ iconNode?: ReactNode;
45
+ /** Plain-text label (used when `textContent` is absent). */
46
+ text?: string;
47
+ /**
48
+ * Multilingual label. When present it renders kang's cross-fading
49
+ * {@link AnimatedText}, cycling english ⇄ chinese per `characterPreference`.
50
+ */
51
+ textContent?: DynamicLanguage;
52
+ /** Which character set (`simplified`/`traditional`) the chinese variant uses. */
53
+ characterPreference?: CharacterPreference;
54
+ /** Cross-fade the label (true) or hold a single static variant (false). Default true. */
55
+ animate?: boolean;
56
+ /** Max ms between cross-fade cycles, forwarded to AnimatedText. */
57
+ maxDelay?: number;
58
+ /** Trailing action: a chevron (default) or an inline toggle. */
59
+ actionIcon?: ListItemActionName;
60
+ /** Row click handler (used when `actionIcon !== 'switch'`). */
61
+ onClick?: () => void;
62
+ /** Inline style passthrough on the `<li>`. */
63
+ styles?: CSSProperties;
64
+ /** Toggle state when `actionIcon === 'switch'` (controlled). */
65
+ switchChecked?: boolean;
66
+ /** Fired with the next toggle value when `actionIcon === 'switch'`. */
67
+ onSwitchChange?: (checked: boolean) => void;
68
+ /** Which language to show when `animate` is false. Forwarded to AnimatedText. */
69
+ staticLanguage?: StaticLanguage;
70
+ };
71
+ export declare const ListItem: ({ icon, iconNode, text, textContent, characterPreference, animate, maxDelay, actionIcon, onClick, styles, switchChecked, onSwitchChange, staticLanguage, }: ListItemProps) => ReactElement;
72
+ export { UnorderedListItemContainer } from './list-item.styles.js';
73
+ export default ListItem;
74
+ //# sourceMappingURL=list-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item.d.ts","sourceRoot":"","sources":["../src/list-item.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAGN,KAAK,aAAa,EAElB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,MAAM,OAAO,CAAC;AAGf,OAAO,KAAK,EACX,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,MAAM,eAAe,CAAC;AAcvB,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,OAAO,GAAG,WAAW,CAAC;AACnE,sFAAsF;AACtF,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAmFtD,MAAM,MAAM,aAAa,GAAG;IAC3B,kFAAkF;IAClF,IAAI,EAAE,gBAAgB,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,iFAAiF;IACjF,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,yFAAyF;IACzF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,iFAAiF;IACjF,cAAc,CAAC,EAAE,cAAc,CAAC;CAChC,CAAC;AAoCF,eAAO,MAAM,QAAQ,+JAclB,aAAa,KAAG,YA2DlB,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEnE,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,105 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ListItem + UnorderedListItemContainer — a pressable settings/menu row and its
4
+ * list wrapper.
5
+ *
6
+ * Ported from ymy-components (`./collections/ListItem` + `./collections/
7
+ * ListItem.styles`), preserving the exact public API the xunzi call sites
8
+ * (`AuthSection`, `Profile`) drive, so re-pointing them at kang is a pure import
9
+ * swap. A row renders a leading icon, a label, and a trailing action (a chevron,
10
+ * or an inline Material toggle when `actionIcon === 'switch'`), with a Material
11
+ * ripple on press.
12
+ *
13
+ * kang-specific upgrades / adaptations:
14
+ * - **Press feedback** uses kang's shared `Ripple` / `useRipple` primitives
15
+ * (themed off `theme.colors.ripple`), replacing ymy's bespoke ripple wiring.
16
+ * - **Icons:** ymy hard-depended on `react-icons` (MdTranslate / MdOutlineWbSunny
17
+ * / MdChevronRight). To keep kang dependency-light and domain-free, the same
18
+ * glyphs ship as inline SVGs (identical Material-icons path data), selectable
19
+ * via the `icon` string. Consumers may override the leading glyph with any node
20
+ * via `iconNode` — the same override pattern as BackButton / CircleIconButton.
21
+ * - **Text:** the `textContent` path maps the app's `DynamicLanguage` model onto
22
+ * kang's domain-free `AnimatedText` (`variants` / `staticIndex` / `sizers`),
23
+ * exactly as xunzi's AnimatedText adapter does — so language knowledge stays in
24
+ * the shared language types and the motion stays in `AnimatedText`.
25
+ * - **Toggle:** ymy rendered a separate `ToggleSwitch`; that Material toggle is
26
+ * inlined (controlled or uncontrolled) so kang needn't ship a ToggleSwitch yet.
27
+ *
28
+ * `styled-components`, `@react-spring/web` (via AnimatedText) and `react` are the
29
+ * only things this module pulls in, all optional peer deps.
30
+ */
31
+ import { useState, } from 'react';
32
+ import AnimatedText from './animated-text.js';
33
+ import { Ripple, useRipple } from './ripple.js';
34
+ import { ListItemContainer, ListItemContent, ListItemIcon, ListItemLeftContent, ListItemText, SwitchContainer, SwitchInput, SwitchRipple, SwitchThumb, SwitchTrack, } from './list-item.styles.js';
35
+ /** Inline MdTranslate (react-icons/md) — Material-icons path data, glyph unchanged. */
36
+ const TranslateIcon = ({ size }) => (_jsxs("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 24 24", height: size, width: size, xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: [_jsx("path", { fill: "none", d: "M0 0h24v24H0z" }), _jsx("path", { d: "m12.87 15.07-2.54-2.51.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7 1.62-4.33L19.12 17h-3.24z" })] }));
37
+ /** Inline MdOutlineWbSunny (react-icons/md) — Material-icons path data, glyph unchanged. */
38
+ const SunnyIcon = ({ size }) => (_jsxs("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 24 24", height: size, width: size, xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: [_jsx("path", { fill: "none", d: "M0 0h24v24H0V0z" }), _jsx("path", { d: "m6.76 4.84-1.8-1.79-1.41 1.41 1.79 1.79zM1 10.5h3v2H1zM11 .55h2V3.5h-2zm8.04 2.495 1.408 1.407-1.79 1.79-1.407-1.408zm-1.8 15.115 1.79 1.8 1.41-1.41-1.8-1.79zM20 10.5h3v2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm-1 4h2v2.95h-2zm-7.45-.96 1.41 1.41 1.79-1.8-1.41-1.41z" })] }));
39
+ /**
40
+ * The "character" glyph: the literal Chinese character 字, rendered as text
41
+ * (ymy did the same — not an SVG icon).
42
+ */
43
+ const CharacterIcon = ({ size }) => (_jsx("span", { style: {
44
+ fontSize: size,
45
+ height: size,
46
+ lineHeight: size,
47
+ display: 'inline-flex',
48
+ alignItems: 'center',
49
+ }, children: "\u5B57" }));
50
+ /** Inline MdChevronRight (react-icons/md) — Material-icons path data, glyph unchanged. */
51
+ const ChevronRightIcon = () => (_jsxs("svg", { stroke: "currentColor", fill: "currentColor", strokeWidth: "0", viewBox: "0 0 24 24", height: "1em", width: "1em", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", focusable: "false", children: [_jsx("path", { fill: "none", d: "M0 0h24v24H0z" }), _jsx("path", { d: "M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" })] }));
52
+ const LEADING_ICONS = {
53
+ translate: TranslateIcon,
54
+ sunny: SunnyIcon,
55
+ character: CharacterIcon,
56
+ };
57
+ /**
58
+ * Inline Material toggle (ymy's `ToggleSwitch`). Controlled when `checked` is
59
+ * supplied, otherwise uncontrolled. Stops click propagation so toggling the
60
+ * switch doesn't also fire the row's click.
61
+ */
62
+ function InlineToggle({ checked: controlledChecked, onChange, }) {
63
+ const [internalChecked, setInternalChecked] = useState(false);
64
+ const isControlled = controlledChecked !== undefined;
65
+ const checked = isControlled ? controlledChecked : internalChecked;
66
+ const handleChange = (e) => {
67
+ // Blur immediately to drop the focus highlight (matches ymy).
68
+ e.target.blur();
69
+ const next = !checked;
70
+ if (!isControlled)
71
+ setInternalChecked(next);
72
+ onChange?.(next);
73
+ };
74
+ return (_jsxs(SwitchContainer, { "$checked": checked, onClick: (e) => e.stopPropagation(), children: [_jsx(SwitchInput, { type: "checkbox", checked: checked, onChange: handleChange }), _jsx(SwitchTrack, { "$checked": checked }), _jsx(SwitchRipple, { "$checked": checked }), _jsx(SwitchThumb, { "$checked": checked })] }));
75
+ }
76
+ export const ListItem = ({ icon, iconNode, text, textContent, characterPreference, animate = true, maxDelay, actionIcon = 'chevron', onClick, styles, switchChecked, onSwitchChange, staticLanguage, }) => {
77
+ const { ripple, trigger, isTarget } = useRipple();
78
+ const handleRowClick = (e) => {
79
+ trigger(e, 'row');
80
+ if (actionIcon === 'switch') {
81
+ onSwitchChange?.(!switchChecked);
82
+ }
83
+ else {
84
+ onClick?.();
85
+ }
86
+ };
87
+ const LeadingIcon = LEADING_ICONS[icon];
88
+ const renderTrailingAction = () => actionIcon === 'switch' ? (_jsx(InlineToggle, { checked: switchChecked, onChange: onSwitchChange })) : (_jsx(ChevronRightIcon, {}));
89
+ // Map the app's DynamicLanguage onto kang's domain-free AnimatedText, exactly
90
+ // as xunzi's AnimatedText adapter does, so output is identical to ymy.
91
+ let labelNode = text;
92
+ if (textContent) {
93
+ const charPref = characterPreference ?? 'simplified';
94
+ const chinese = charPref === 'traditional' ? textContent.traditional : textContent.simplified;
95
+ labelNode = (_jsx(AnimatedText, { variants: [textContent.english, chinese], animate: animate, staticIndex: staticLanguage === 'chinese' ? 1 : 0, sizers: [
96
+ textContent.english,
97
+ textContent.simplified,
98
+ textContent.traditional,
99
+ ], maxDelay: maxDelay }));
100
+ }
101
+ return (_jsxs(ListItemContainer, { onClick: handleRowClick, style: styles, children: [isTarget('row') && ripple && (_jsx(Ripple, { "$x": ripple.x, "$y": ripple.y }, ripple.key)), _jsxs(ListItemContent, { children: [_jsxs(ListItemLeftContent, { children: [_jsx(ListItemIcon, { children: iconNode !== undefined ? iconNode : _jsx(LeadingIcon, { size: "1rem" }) }), _jsx(ListItemText, { children: labelNode })] }), _jsx(ListItemIcon, { children: renderTrailingAction() })] })] }));
102
+ };
103
+ export { UnorderedListItemContainer } from './list-item.styles.js';
104
+ export default ListItem;
105
+ //# sourceMappingURL=list-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item.js","sourceRoot":"","sources":["../src/list-item.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Styled building blocks for {@link ListItem} and its list container.
3
+ *
4
+ * Ported from ymy-components (`./collections/ListItem.styles` +
5
+ * `./components/ToggleSwitch`) and kept as a co-located pair so the list
6
+ * semantics, spacing and the inline toggle travel with the component. All color
7
+ * values read off styled-components' `props.theme` with literal fallbacks (the
8
+ * same fallbacks ymy used), so the primitives render sensibly with or without a
9
+ * themed `ThemeProvider` — matching the rest of kang (ripple.ts,
10
+ * circle-icon-button.tsx).
11
+ *
12
+ * `styled-components` is an optional peer dependency, pulled in only by this
13
+ * module (and the component that imports it). Consumers importing just the
14
+ * string / press primitives never load it.
15
+ */
16
+ /**
17
+ * The list container: a `<ul>` that lays its {@link ListItem} children out in a
18
+ * centered column with the browser's default inline padding removed. Ported 1:1
19
+ * from ymy so list semantics + spacing are preserved.
20
+ */
21
+ export declare const UnorderedListItemContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLUListElement>, HTMLUListElement>, never>>> & string;
22
+ /** The pressable row element — a relatively-positioned `<li>` that clips its ripple. */
23
+ export declare const ListItemContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, never>>> & string;
24
+ /** Row inner layout: left content (icon + text) pushed apart from the trailing action. */
25
+ export declare const ListItemContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
26
+ /** Left cluster: the leading icon and the text, spaced apart. */
27
+ export declare const ListItemLeftContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
28
+ /** Wrapper that vertically centers an icon (leading or trailing). */
29
+ export declare const ListItemIcon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
30
+ /** The row's text span. */
31
+ export declare const ListItemText: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>>> & string;
32
+ /** Hover/focus ripple disc behind the thumb (Material affordance). */
33
+ export declare const SwitchRipple: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
34
+ $checked: boolean;
35
+ }, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
36
+ $checked: boolean;
37
+ }, never>>> & string;
38
+ /** The toggle's label/container; stops click propagation so the row isn't double-fired. */
39
+ export declare const SwitchContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "$checked"> & {
40
+ $checked: boolean;
41
+ }, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "$checked"> & {
42
+ $checked: boolean;
43
+ }, never>>> & string;
44
+ export declare const SwitchInput: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never> & Partial<Pick<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, never>>> & string;
45
+ export declare const SwitchTrack: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
46
+ $checked: boolean;
47
+ }, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
48
+ $checked: boolean;
49
+ }, never>>> & string;
50
+ export declare const SwitchThumb: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
51
+ $checked: boolean;
52
+ }, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "$checked"> & {
53
+ $checked: boolean;
54
+ }, never>>> & string;
55
+ //# sourceMappingURL=list-item.styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item.styles.d.ts","sourceRoot":"","sources":["../src/list-item.styles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAuBH;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,+VAKtC,CAAC;AAEF,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,uVAS7B,CAAC;AAEF,0FAA0F;AAC1F,eAAO,MAAM,eAAe,uVAM3B,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,mBAAmB,uVAK/B,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,YAAY,uVAKxB,CAAC;AAEF,2BAA2B;AAC3B,eAAO,MAAM,YAAY,2VAGxB,CAAC;AASF,sEAAsE;AACtE,eAAO,MAAM,YAAY;cAA2B,OAAO;;cAAP,OAAO;oBAY1D,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,eAAe;cAA4B,OAAO;;cAAP,OAAO;oBA0B9D,CAAC;AAEF,eAAO,MAAM,WAAW,yWAKvB,CAAC;AAEF,eAAO,MAAM,WAAW;cAA2B,OAAO;;cAAP,OAAO;oBAUzD,CAAC;AAEF,eAAO,MAAM,WAAW;cAA2B,OAAO;;cAAP,OAAO;oBAyBzD,CAAC"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Styled building blocks for {@link ListItem} and its list container.
3
+ *
4
+ * Ported from ymy-components (`./collections/ListItem.styles` +
5
+ * `./components/ToggleSwitch`) and kept as a co-located pair so the list
6
+ * semantics, spacing and the inline toggle travel with the component. All color
7
+ * values read off styled-components' `props.theme` with literal fallbacks (the
8
+ * same fallbacks ymy used), so the primitives render sensibly with or without a
9
+ * themed `ThemeProvider` — matching the rest of kang (ripple.ts,
10
+ * circle-icon-button.tsx).
11
+ *
12
+ * `styled-components` is an optional peer dependency, pulled in only by this
13
+ * module (and the component that imports it). Consumers importing just the
14
+ * string / press primitives never load it.
15
+ */
16
+ // Named import (not the default) so styled-components resolves consistently
17
+ // across bundler and raw ESM/CJS environments — matches ripple.ts.
18
+ import { styled } from 'styled-components';
19
+ /**
20
+ * The list container: a `<ul>` that lays its {@link ListItem} children out in a
21
+ * centered column with the browser's default inline padding removed. Ported 1:1
22
+ * from ymy so list semantics + spacing are preserved.
23
+ */
24
+ export const UnorderedListItemContainer = styled.ul `
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: center;
28
+ padding-inline-start: unset;
29
+ `;
30
+ /** The pressable row element — a relatively-positioned `<li>` that clips its ripple. */
31
+ export const ListItemContainer = styled.li `
32
+ position: relative;
33
+ list-style: none;
34
+ cursor: pointer;
35
+ overflow: hidden;
36
+ -webkit-tap-highlight-color: transparent;
37
+ border-bottom: 1px solid
38
+ ${({ theme }) => theme?.colors?.scrimLight ?? 'rgba(0, 0, 0, 0.3)'};
39
+ `;
40
+ /** Row inner layout: left content (icon + text) pushed apart from the trailing action. */
41
+ export const ListItemContent = styled.div `
42
+ display: flex;
43
+ flex-direction: row;
44
+ justify-content: space-between;
45
+ align-items: center;
46
+ padding: 0.5rem 0.75rem;
47
+ `;
48
+ /** Left cluster: the leading icon and the text, spaced apart. */
49
+ export const ListItemLeftContent = styled.div `
50
+ display: flex;
51
+ flex-direction: row;
52
+ gap: 2rem;
53
+ align-items: center;
54
+ `;
55
+ /** Wrapper that vertically centers an icon (leading or trailing). */
56
+ export const ListItemIcon = styled.div `
57
+ display: flex;
58
+ flex-direction: column;
59
+ justify-content: center;
60
+ color: ${({ theme }) => theme?.colors?.onSurface ?? 'black'};
61
+ `;
62
+ /** The row's text span. */
63
+ export const ListItemText = styled.span `
64
+ font-size: 1rem;
65
+ color: ${({ theme }) => theme?.colors?.onSurface ?? 'black'};
66
+ `;
67
+ /* ── Inline toggle switch ──────────────────────────────────────────────────
68
+ * ymy's ListItem rendered its `ToggleSwitch` component when `actionIcon` was
69
+ * 'switch'. kang has no ToggleSwitch yet, so the same Material-style toggle is
70
+ * inlined here, reading kang's `toggle*` theme tokens with the identical literal
71
+ * fallbacks ymy used. Look + behavior are preserved 1:1.
72
+ */
73
+ /** Hover/focus ripple disc behind the thumb (Material affordance). */
74
+ export const SwitchRipple = styled.span `
75
+ position: absolute;
76
+ top: 50%;
77
+ left: ${({ $checked }) => ($checked ? '14px' : '0px')};
78
+ transform: translate(-50%, -50%) translateX(50%);
79
+ width: 38px;
80
+ height: 38px;
81
+ border-radius: 50%;
82
+ background-color: transparent;
83
+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
84
+ left 400ms cubic-bezier(0.34, 1.56, 0.64, 1);
85
+ pointer-events: none;
86
+ `;
87
+ /** The toggle's label/container; stops click propagation so the row isn't double-fired. */
88
+ export const SwitchContainer = styled.label `
89
+ position: relative;
90
+ display: inline-flex;
91
+ align-items: center;
92
+ cursor: pointer;
93
+ -webkit-tap-highlight-color: transparent;
94
+
95
+ @media (hover: hover) {
96
+ &:hover ${SwitchRipple} {
97
+ background-color: ${({ $checked, theme }) => $checked
98
+ ? theme?.colors?.toggleHoverOn ??
99
+ 'rgba(72, 159, 181, 0.08)'
100
+ : theme?.colors?.toggleHoverOff ??
101
+ 'rgba(0, 0, 0, 0.04)'};
102
+ }
103
+ }
104
+
105
+ &:focus-within ${SwitchRipple} {
106
+ background-color: ${({ $checked, theme }) => $checked
107
+ ? theme?.colors?.toggleFocusOn ??
108
+ 'rgba(72, 159, 181, 0.12)'
109
+ : theme?.colors?.toggleFocusOff ??
110
+ 'rgba(0, 0, 0, 0.06)'};
111
+ }
112
+ `;
113
+ export const SwitchInput = styled.input `
114
+ opacity: 0;
115
+ width: 0;
116
+ height: 0;
117
+ position: absolute;
118
+ `;
119
+ export const SwitchTrack = styled.span `
120
+ width: 34px;
121
+ height: 14px;
122
+ background-color: ${({ $checked, theme }) => $checked
123
+ ? theme?.colors?.toggleTrackOn ??
124
+ 'rgba(72, 159, 181, 0.5)'
125
+ : theme?.colors?.toggleTrackOff ?? 'rgba(0, 0, 0, 0.38)'};
126
+ border-radius: 7px;
127
+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
128
+ `;
129
+ export const SwitchThumb = styled.span `
130
+ position: absolute;
131
+ top: 50%;
132
+ left: ${({ $checked }) => ($checked ? '14px' : '0px')};
133
+ transform: translateY(-50%) scale(${({ $checked }) => ($checked ? 1.1 : 1)});
134
+ width: 20px;
135
+ height: 20px;
136
+ background-color: ${({ $checked, theme }) => $checked
137
+ ? theme?.colors?.toggleThumbOn ?? '#489fb5'
138
+ : theme?.colors?.toggleThumbOff ?? '#fafafa'};
139
+ border-radius: 50%;
140
+ box-shadow: 0px 2px 1px -1px
141
+ ${({ theme }) => theme?.colors?.shadowLight ?? 'rgba(0, 0, 0, 0.2)'},
142
+ 0px 1px 1px 0px
143
+ ${({ theme }) => theme?.colors?.shadowLighter ?? 'rgba(0, 0, 0, 0.14)'},
144
+ 0px 1px 3px 0px
145
+ ${({ theme }) => theme?.colors?.shadowLighter ?? 'rgba(0, 0, 0, 0.12)'};
146
+ transition: left 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
147
+ transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
148
+ background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
149
+ pointer-events: none;
150
+ `;
151
+ //# sourceMappingURL=list-item.styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item.styles.js","sourceRoot":"","sources":["../src/list-item.styles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ToggleSwitch — a Material-style on/off switch with an animated thumb.
3
+ *
4
+ * Ported faithfully from ymy-components (`./components/ToggleSwitch`). The public
5
+ * API is preserved 1:1 so xunzi's single re-point site (Profile.tsx, the error-
6
+ * reporting toggle) is a pure import swap: it drives the switch through `checked`
7
+ * + `onChange`, both unchanged here.
8
+ *
9
+ * Behavior (uncontrolled / controlled): if `checked` is provided the component is
10
+ * controlled and renders that value; otherwise it owns internal state seeded by
11
+ * `defaultChecked`. Either way `onChange(next)` fires on toggle (suppressed when
12
+ * `disabled`). The hidden checkbox is blurred on change to drop the focus ring,
13
+ * and the label stops click propagation so it can sit inside clickable rows.
14
+ *
15
+ * Fluid animation (a core principle): the thumb slides + slightly scales between
16
+ * the off/on positions via a spring-like cubic-bezier CSS transition, and the
17
+ * track / ripple cross-fade their colors — preserved exactly from ymy.
18
+ *
19
+ * Theming: track / thumb / hover / focus colors read off styled-components'
20
+ * `props.theme.colors.toggle*` tokens (assembled by kang's `buildTheme`), with the
21
+ * same literal fallbacks ymy shipped so it renders sensibly with or without a
22
+ * `ThemeProvider`. `styled-components` is an optional peer dependency, used only by
23
+ * this module.
24
+ */
25
+ import { type ReactElement } from 'react';
26
+ export type ToggleSwitchProps = {
27
+ /** Controlled checked state. When provided, the component is controlled. */
28
+ checked?: boolean;
29
+ /** Initial checked state for the uncontrolled case. Defaults to `false`. */
30
+ defaultChecked?: boolean;
31
+ /** Fired with the next checked value whenever the switch is toggled. */
32
+ onChange?: (checked: boolean) => void;
33
+ /** When `true`, the switch is non-interactive and suppresses `onChange`. */
34
+ disabled?: boolean;
35
+ };
36
+ export declare const ToggleSwitch: ({ checked: controlledChecked, defaultChecked, onChange, disabled, }: ToggleSwitchProps) => ReactElement;
37
+ export default ToggleSwitch;
38
+ //# sourceMappingURL=toggle-switch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle-switch.d.ts","sourceRoot":"","sources":["../src/toggle-switch.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAoB,KAAK,YAAY,EAAY,MAAM,OAAO,CAAC;AAqGtE,MAAM,MAAM,iBAAiB,GAAG;IAC/B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,YAAY,wEAKtB,iBAAiB,KAAG,YAgCtB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -0,0 +1,118 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ToggleSwitch — a Material-style on/off switch with an animated thumb.
4
+ *
5
+ * Ported faithfully from ymy-components (`./components/ToggleSwitch`). The public
6
+ * API is preserved 1:1 so xunzi's single re-point site (Profile.tsx, the error-
7
+ * reporting toggle) is a pure import swap: it drives the switch through `checked`
8
+ * + `onChange`, both unchanged here.
9
+ *
10
+ * Behavior (uncontrolled / controlled): if `checked` is provided the component is
11
+ * controlled and renders that value; otherwise it owns internal state seeded by
12
+ * `defaultChecked`. Either way `onChange(next)` fires on toggle (suppressed when
13
+ * `disabled`). The hidden checkbox is blurred on change to drop the focus ring,
14
+ * and the label stops click propagation so it can sit inside clickable rows.
15
+ *
16
+ * Fluid animation (a core principle): the thumb slides + slightly scales between
17
+ * the off/on positions via a spring-like cubic-bezier CSS transition, and the
18
+ * track / ripple cross-fade their colors — preserved exactly from ymy.
19
+ *
20
+ * Theming: track / thumb / hover / focus colors read off styled-components'
21
+ * `props.theme.colors.toggle*` tokens (assembled by kang's `buildTheme`), with the
22
+ * same literal fallbacks ymy shipped so it renders sensibly with or without a
23
+ * `ThemeProvider`. `styled-components` is an optional peer dependency, used only by
24
+ * this module.
25
+ */
26
+ import { useState } from 'react';
27
+ // Named import (not the default) so styled-components resolves consistently
28
+ // across bundler and raw ESM/CJS environments — matches ripple.ts / the other
29
+ // styled kang primitives.
30
+ import { styled } from 'styled-components';
31
+ const c = (theme) => theme?.colors ?? {};
32
+ const SwitchInput = styled.input `
33
+ opacity: 0;
34
+ width: 0;
35
+ height: 0;
36
+ position: absolute;
37
+ `;
38
+ const RippleEffect = styled.span `
39
+ position: absolute;
40
+ top: 50%;
41
+ left: ${({ $checked }) => ($checked ? '14px' : '0px')};
42
+ transform: translate(-50%, -50%) translateX(50%);
43
+ width: 38px;
44
+ height: 38px;
45
+ border-radius: 50%;
46
+ background-color: transparent;
47
+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1),
48
+ left 400ms cubic-bezier(0.34, 1.56, 0.64, 1);
49
+ pointer-events: none;
50
+ `;
51
+ const SwitchContainer = styled.label `
52
+ position: relative;
53
+ display: inline-flex;
54
+ align-items: center;
55
+ cursor: pointer;
56
+ -webkit-tap-highlight-color: transparent;
57
+
58
+ @media (hover: hover) {
59
+ &:hover ${RippleEffect} {
60
+ background-color: ${({ $checked, theme }) => $checked
61
+ ? c(theme).toggleHoverOn ?? 'rgba(72, 159, 181, 0.08)'
62
+ : c(theme).toggleHoverOff ?? 'rgba(0, 0, 0, 0.04)'};
63
+ }
64
+ }
65
+
66
+ &:focus-within ${RippleEffect} {
67
+ background-color: ${({ $checked, theme }) => $checked
68
+ ? c(theme).toggleFocusOn ?? 'rgba(72, 159, 181, 0.12)'
69
+ : c(theme).toggleFocusOff ?? 'rgba(0, 0, 0, 0.06)'};
70
+ }
71
+ `;
72
+ const SwitchTrack = styled.span `
73
+ width: 34px;
74
+ height: 14px;
75
+ background-color: ${({ $checked, theme }) => $checked
76
+ ? c(theme).toggleTrackOn ?? 'rgba(72, 159, 181, 0.5)'
77
+ : c(theme).toggleTrackOff ?? 'rgba(0, 0, 0, 0.38)'};
78
+ border-radius: 7px;
79
+ transition: background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
80
+ `;
81
+ const SwitchThumb = styled.span `
82
+ position: absolute;
83
+ top: 50%;
84
+ left: ${({ $checked }) => ($checked ? '14px' : '0px')};
85
+ transform: translateY(-50%) scale(${({ $checked }) => ($checked ? 1.1 : 1)});
86
+ width: 20px;
87
+ height: 20px;
88
+ background-color: ${({ $checked, theme }) => $checked
89
+ ? c(theme).toggleThumbOn ?? '#489fb5'
90
+ : c(theme).toggleThumbOff ?? '#fafafa'};
91
+ border-radius: 50%;
92
+ box-shadow: 0px 2px 1px -1px ${({ theme }) => c(theme).shadowLight ?? 'rgba(0, 0, 0, 0.2)'},
93
+ 0px 1px 1px 0px ${({ theme }) => c(theme).shadowLighter ?? 'rgba(0, 0, 0, 0.14)'},
94
+ 0px 1px 3px 0px ${({ theme }) => c(theme).shadowLighter ?? 'rgba(0, 0, 0, 0.12)'};
95
+ transition: left 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
96
+ transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1),
97
+ background-color 150ms cubic-bezier(0.4, 0, 0.2, 1);
98
+ pointer-events: none;
99
+ `;
100
+ export const ToggleSwitch = ({ checked: controlledChecked, defaultChecked = false, onChange, disabled = false, }) => {
101
+ const [internalChecked, setInternalChecked] = useState(defaultChecked);
102
+ const isControlled = controlledChecked !== undefined;
103
+ const checked = isControlled ? controlledChecked : internalChecked;
104
+ const handleChange = (e) => {
105
+ if (disabled)
106
+ return;
107
+ // Blur immediately to remove the focus highlight.
108
+ e.target.blur();
109
+ const newValue = !checked;
110
+ if (!isControlled) {
111
+ setInternalChecked(newValue);
112
+ }
113
+ onChange?.(newValue);
114
+ };
115
+ return (_jsxs(SwitchContainer, { "$checked": checked, onClick: (e) => e.stopPropagation(), children: [_jsx(SwitchInput, { type: "checkbox", checked: checked, onChange: handleChange, disabled: disabled }), _jsx(SwitchTrack, { "$checked": checked }), _jsx(RippleEffect, { "$checked": checked }), _jsx(SwitchThumb, { "$checked": checked })] }));
116
+ };
117
+ export default ToggleSwitch;
118
+ //# sourceMappingURL=toggle-switch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle-switch.js","sourceRoot":"","sources":["../src/toggle-switch.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kang-components",
3
- "version": "0.5.0",
4
- "description": "Generic, domain-free React UI primitives (CSS-first press feedback, delayed-action hook, spring presets, cross-fading text).",
3
+ "version": "0.7.0",
4
+ "description": "Generic, domain-free React UI primitives (CSS-first press feedback, delayed-action hook, spring presets, cross-fading text, circle icon button).",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {