kang-components 0.6.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/badge.d.ts +34 -0
- package/dist/badge.d.ts.map +1 -0
- package/dist/badge.js +46 -0
- package/dist/badge.js.map +1 -0
- package/dist/bottom-sheet.d.ts +60 -0
- package/dist/bottom-sheet.d.ts.map +1 -0
- package/dist/bottom-sheet.js +201 -0
- package/dist/bottom-sheet.js.map +1 -0
- package/dist/confirm-dialog.d.ts +40 -0
- package/dist/confirm-dialog.d.ts.map +1 -0
- package/dist/confirm-dialog.js +74 -0
- package/dist/confirm-dialog.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/list-item.d.ts +74 -0
- package/dist/list-item.d.ts.map +1 -0
- package/dist/list-item.js +105 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list-item.styles.d.ts +55 -0
- package/dist/list-item.styles.d.ts.map +1 -0
- package/dist/list-item.styles.js +151 -0
- package/dist/list-item.styles.js.map +1 -0
- package/dist/toggle-switch.d.ts +38 -0
- package/dist/toggle-switch.d.ts.map +1 -0
- package/dist/toggle-switch.js +118 -0
- package/dist/toggle-switch.js.map +1 -0
- package/dist/use-viewport-size.d.ts +16 -0
- package/dist/use-viewport-size.d.ts.map +1 -0
- package/dist/use-viewport-size.js +38 -0
- package/dist/use-viewport-size.js.map +1 -0
- package/package.json +6 -1
|
@@ -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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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ViewportSize {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Hook to track viewport dimensions with debounced updates.
|
|
7
|
+
* Listens to resize and orientation change events.
|
|
8
|
+
*
|
|
9
|
+
* Ported from ymy-components (`./hooks/useViewportSize`) preserving its public
|
|
10
|
+
* API exactly so xunzi can re-point as a pure import swap.
|
|
11
|
+
*
|
|
12
|
+
* @param debounceMs - Debounce delay in milliseconds (default: 100)
|
|
13
|
+
* @returns ViewportSize - Current viewport width and height
|
|
14
|
+
*/
|
|
15
|
+
export declare function useViewportSize(debounceMs?: number): ViewportSize;
|
|
16
|
+
//# sourceMappingURL=use-viewport-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-viewport-size.d.ts","sourceRoot":"","sources":["../src/use-viewport-size.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,UAAU,SAAM,GAAG,YAAY,CA8B9D"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook to track viewport dimensions with debounced updates.
|
|
4
|
+
* Listens to resize and orientation change events.
|
|
5
|
+
*
|
|
6
|
+
* Ported from ymy-components (`./hooks/useViewportSize`) preserving its public
|
|
7
|
+
* API exactly so xunzi can re-point as a pure import swap.
|
|
8
|
+
*
|
|
9
|
+
* @param debounceMs - Debounce delay in milliseconds (default: 100)
|
|
10
|
+
* @returns ViewportSize - Current viewport width and height
|
|
11
|
+
*/
|
|
12
|
+
export function useViewportSize(debounceMs = 100) {
|
|
13
|
+
const [size, setSize] = useState({
|
|
14
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
15
|
+
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
16
|
+
});
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
let timeoutId;
|
|
19
|
+
const handleResize = () => {
|
|
20
|
+
clearTimeout(timeoutId);
|
|
21
|
+
timeoutId = setTimeout(() => {
|
|
22
|
+
setSize({
|
|
23
|
+
width: window.innerWidth,
|
|
24
|
+
height: window.innerHeight,
|
|
25
|
+
});
|
|
26
|
+
}, debounceMs);
|
|
27
|
+
};
|
|
28
|
+
window.addEventListener('resize', handleResize);
|
|
29
|
+
window.addEventListener('orientationchange', handleResize);
|
|
30
|
+
return () => {
|
|
31
|
+
clearTimeout(timeoutId);
|
|
32
|
+
window.removeEventListener('resize', handleResize);
|
|
33
|
+
window.removeEventListener('orientationchange', handleResize);
|
|
34
|
+
};
|
|
35
|
+
}, [debounceMs]);
|
|
36
|
+
return size;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=use-viewport-size.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-viewport-size.js","sourceRoot":"","sources":["../src/use-viewport-size.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAO5C;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,UAAU,GAAG,GAAG;IAC/C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAe;QAC9C,KAAK,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;KAC9D,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,SAAwC,CAAC;QAE7C,MAAM,YAAY,GAAG,GAAG,EAAE;YACzB,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC3B,OAAO,CAAC;oBACP,KAAK,EAAE,MAAM,CAAC,UAAU;oBACxB,MAAM,EAAE,MAAM,CAAC,WAAW;iBAC1B,CAAC,CAAC;YACJ,CAAC,EAAE,UAAU,CAAC,CAAC;QAChB,CAAC,CAAC;QAEF,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QAChD,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAE3D,OAAO,GAAG,EAAE;YACX,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YACnD,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QAC/D,CAAC,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,OAAO,IAAI,CAAC;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kang-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
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",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"@react-spring/web": ">=9",
|
|
32
|
+
"@use-gesture/react": ">=10",
|
|
32
33
|
"react": ">=18",
|
|
33
34
|
"styled-components": ">=6"
|
|
34
35
|
},
|
|
@@ -36,6 +37,9 @@
|
|
|
36
37
|
"@react-spring/web": {
|
|
37
38
|
"optional": true
|
|
38
39
|
},
|
|
40
|
+
"@use-gesture/react": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
39
43
|
"react": {
|
|
40
44
|
"optional": true
|
|
41
45
|
},
|
|
@@ -49,6 +53,7 @@
|
|
|
49
53
|
"@testing-library/react": "^16.1.0",
|
|
50
54
|
"@types/react": "^18.3.18",
|
|
51
55
|
"@types/react-dom": "^18.3.5",
|
|
56
|
+
"@use-gesture/react": "^10.3.1",
|
|
52
57
|
"@vitejs/plugin-react": "^4.3.4",
|
|
53
58
|
"jsdom": "^25.0.1",
|
|
54
59
|
"react": "^18.3.1",
|