kang-components 0.0.1 → 0.2.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/README.md +92 -40
- package/dist/action-sheet.d.ts +27 -0
- package/dist/action-sheet.d.ts.map +1 -0
- package/dist/action-sheet.js +53 -0
- package/dist/action-sheet.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/press.d.ts +42 -0
- package/dist/press.d.ts.map +1 -0
- package/dist/press.js +60 -0
- package/dist/press.js.map +1 -0
- package/dist/use-animated-action.d.ts +2 -0
- package/dist/use-animated-action.d.ts.map +1 -0
- package/dist/use-animated-action.js +30 -0
- package/dist/use-animated-action.js.map +1 -0
- package/package.json +24 -26
- package/dist/kang-components.js +0 -5
- package/dist/kang-components.umd.cjs +0 -1
- package/dist/vite.svg +0 -1
package/README.md
CHANGED
|
@@ -1,50 +1,102 @@
|
|
|
1
|
-
#
|
|
1
|
+
# kang-components
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Generic, domain-free React UI primitives. Built to be consumed by Xunzi (and
|
|
4
|
+
anything else) while it migrates off `ymy-components` — see the
|
|
5
|
+
[Xunzi straddle epic](https://github.com/LoganConnor44/xunzi/issues/294).
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
## Design constraints
|
|
6
8
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
+
- **No app domain knowledge.** No HSK, challenge, friend, route, or Redux
|
|
10
|
+
concepts. Primitives only.
|
|
11
|
+
- **CSS-first.** Simple interaction primitives return plain CSS strings — no
|
|
12
|
+
CSS-in-JS runtime dependency. Use JS animation only when it earns the cost.
|
|
13
|
+
- **Additive, non-breaking APIs** before each manual npm publication.
|
|
9
14
|
|
|
10
|
-
##
|
|
15
|
+
## Install
|
|
11
16
|
|
|
12
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install kang-components
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`react` is an optional peer dependency — only required if you use a hook
|
|
22
|
+
(e.g. `useAnimatedAction`). The press primitives are pure strings and need
|
|
23
|
+
nothing.
|
|
24
|
+
|
|
25
|
+
## Press primitives
|
|
26
|
+
|
|
27
|
+
CSS-first press feedback. Each helper returns a plain CSS string you interpolate
|
|
28
|
+
into your styling layer (styled-components shown):
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import styled from 'styled-components';
|
|
32
|
+
import { pressPrimary, pressSubtle } from 'kang-components';
|
|
33
|
+
|
|
34
|
+
// Action buttons (scale 0.95)
|
|
35
|
+
const Button = styled.button`
|
|
36
|
+
${pressPrimary()}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
// Large tappable surfaces (scale 0.97)
|
|
40
|
+
const Tile = styled.button`
|
|
41
|
+
${pressSubtle()}
|
|
42
|
+
`;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
When the element also transitions other properties, pass them via
|
|
46
|
+
`extraTransition` so they share the one `transition` declaration:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const Row = styled.button`
|
|
50
|
+
${pressSubtle('background-color 0.15s ease-out')}
|
|
51
|
+
`;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
For elements whose `transform` is driven elsewhere (e.g. a JS spring), use the
|
|
55
|
+
`*Scale` variants, which animate the CSS `scale` property instead:
|
|
13
56
|
|
|
14
|
-
|
|
57
|
+
```ts
|
|
58
|
+
import { pressPrimaryScale, pressSubtleScale } from 'kang-components';
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Exports: `pressPrimary`, `pressSubtle`, `pressPrimaryScale`, `pressSubtleScale`,
|
|
62
|
+
plus the constants `BOUNCE_CURVE`, `PRESS_SCALE_PRIMARY`, `PRESS_SCALE_SUBTLE`.
|
|
63
|
+
|
|
64
|
+
## `useAnimatedAction`
|
|
65
|
+
|
|
66
|
+
Delays an action callback so visual feedback (ripple, press animation) is
|
|
67
|
+
perceived before the UI transitions away. Defaults to 180ms; clears pending
|
|
68
|
+
timeouts on unmount.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { useAnimatedAction } from 'kang-components';
|
|
72
|
+
|
|
73
|
+
const act = useAnimatedAction();
|
|
74
|
+
const onClick = () => act(() => navigate('/next'));
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Action-sheet primitives
|
|
78
|
+
|
|
79
|
+
CSS-first layout for a bottom-sheet "actions" panel — a vertical container, a
|
|
80
|
+
list, and tappable action rows with subtle press feedback. Colors stay with the
|
|
81
|
+
consumer: `actionSheetRow` takes the pressed-state background, so Kang carries no
|
|
82
|
+
theme knowledge.
|
|
15
83
|
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
})
|
|
84
|
+
```ts
|
|
85
|
+
import styled from 'styled-components';
|
|
86
|
+
import { actionSheetContainer, actionSheetList, actionSheetRow } from 'kang-components';
|
|
87
|
+
|
|
88
|
+
const Container = styled.div`${actionSheetContainer()}`;
|
|
89
|
+
const List = styled.div`${actionSheetList()}`;
|
|
90
|
+
const Row = styled.button`
|
|
91
|
+
${({ theme }) => actionSheetRow(theme.colors.surfaceVariant)}
|
|
92
|
+
`;
|
|
26
93
|
```
|
|
27
94
|
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export default tseslint.config({
|
|
37
|
-
// Set the react version
|
|
38
|
-
settings: { react: { version: '18.3' } },
|
|
39
|
-
plugins: {
|
|
40
|
-
// Add the react plugin
|
|
41
|
-
react,
|
|
42
|
-
},
|
|
43
|
-
rules: {
|
|
44
|
-
// other rules...
|
|
45
|
-
// Enable its recommended rules
|
|
46
|
-
...react.configs.recommended.rules,
|
|
47
|
-
...react.configs['jsx-runtime'].rules,
|
|
48
|
-
},
|
|
49
|
-
})
|
|
95
|
+
Per-row content (leading icon, label, destructive tint, ripple) is the
|
|
96
|
+
consumer's to layer on top of the row.
|
|
97
|
+
|
|
98
|
+
## Build
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm run build # tsc → dist (ESM + .d.ts)
|
|
50
102
|
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action-sheet layout primitives — CSS-first, domain-free.
|
|
3
|
+
*
|
|
4
|
+
* The shared shape of a bottom-sheet "actions" panel: a vertical container, a
|
|
5
|
+
* list, and tappable action rows with subtle press feedback. Each helper
|
|
6
|
+
* returns a plain CSS string to interpolate into your styling layer.
|
|
7
|
+
*
|
|
8
|
+
* const Container = styled.div`${actionSheetContainer()}`;
|
|
9
|
+
* const List = styled.div`${actionSheetList()}`;
|
|
10
|
+
* const Row = styled.button`${actionSheetRow(theme.colors.surfaceVariant)}`;
|
|
11
|
+
*
|
|
12
|
+
* Colors stay with the consumer: `actionSheetRow` takes the pressed-state
|
|
13
|
+
* background so Kang carries no theme knowledge. Per-row content styling (icon
|
|
14
|
+
* tint, destructive text, etc.) is the consumer's to layer on.
|
|
15
|
+
*/
|
|
16
|
+
/** Vertical action-sheet wrapper: column flex with standard sheet padding. */
|
|
17
|
+
export declare const actionSheetContainer: () => string;
|
|
18
|
+
/** The list of action rows. */
|
|
19
|
+
export declare const actionSheetList: () => string;
|
|
20
|
+
/**
|
|
21
|
+
* A single tappable action row: leading-icon + label layout with subtle press
|
|
22
|
+
* feedback (`pressSubtle`, with a background-color transition). Pass
|
|
23
|
+
* `activeBackground` to tint the pressed state; omit it to leave the pressed
|
|
24
|
+
* background to the consumer.
|
|
25
|
+
*/
|
|
26
|
+
export declare const actionSheetRow: (activeBackground?: string) => string;
|
|
27
|
+
//# sourceMappingURL=action-sheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-sheet.d.ts","sourceRoot":"","sources":["../src/action-sheet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,8EAA8E;AAC9E,eAAO,MAAM,oBAAoB,QAAO,MAKvC,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,eAAe,QAAO,MAGlC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,sBAAuB,MAAM,KAAG,MAiB1D,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action-sheet layout primitives — CSS-first, domain-free.
|
|
3
|
+
*
|
|
4
|
+
* The shared shape of a bottom-sheet "actions" panel: a vertical container, a
|
|
5
|
+
* list, and tappable action rows with subtle press feedback. Each helper
|
|
6
|
+
* returns a plain CSS string to interpolate into your styling layer.
|
|
7
|
+
*
|
|
8
|
+
* const Container = styled.div`${actionSheetContainer()}`;
|
|
9
|
+
* const List = styled.div`${actionSheetList()}`;
|
|
10
|
+
* const Row = styled.button`${actionSheetRow(theme.colors.surfaceVariant)}`;
|
|
11
|
+
*
|
|
12
|
+
* Colors stay with the consumer: `actionSheetRow` takes the pressed-state
|
|
13
|
+
* background so Kang carries no theme knowledge. Per-row content styling (icon
|
|
14
|
+
* tint, destructive text, etc.) is the consumer's to layer on.
|
|
15
|
+
*/
|
|
16
|
+
import { pressSubtle } from './press.js';
|
|
17
|
+
/** Vertical action-sheet wrapper: column flex with standard sheet padding. */
|
|
18
|
+
export const actionSheetContainer = () => `
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
gap: 1rem;
|
|
22
|
+
padding: 0.5rem 0;
|
|
23
|
+
`;
|
|
24
|
+
/** The list of action rows. */
|
|
25
|
+
export const actionSheetList = () => `
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
`;
|
|
29
|
+
/**
|
|
30
|
+
* A single tappable action row: leading-icon + label layout with subtle press
|
|
31
|
+
* feedback (`pressSubtle`, with a background-color transition). Pass
|
|
32
|
+
* `activeBackground` to tint the pressed state; omit it to leave the pressed
|
|
33
|
+
* background to the consumer.
|
|
34
|
+
*/
|
|
35
|
+
export const actionSheetRow = (activeBackground) => `
|
|
36
|
+
position: relative;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: 1rem;
|
|
40
|
+
padding: 1rem;
|
|
41
|
+
background: none;
|
|
42
|
+
border: none;
|
|
43
|
+
border-radius: 0.75rem;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
${pressSubtle('background-color 0.15s ease-out')}
|
|
47
|
+
-webkit-tap-highlight-color: transparent;
|
|
48
|
+
${activeBackground ? `
|
|
49
|
+
&:active {
|
|
50
|
+
background-color: ${activeBackground};
|
|
51
|
+
}` : ''}
|
|
52
|
+
`;
|
|
53
|
+
//# sourceMappingURL=action-sheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-sheet.js","sourceRoot":"","sources":["../src/action-sheet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,8EAA8E;AAC9E,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAW,EAAE,CAAC;;;;;CAKjD,CAAC;AAEF,+BAA+B;AAC/B,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE,CAAC;;;CAG5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,gBAAyB,EAAU,EAAE,CAAC;;;;;;;;;;;GAWlE,WAAW,CAAC,iCAAiC,CAAC;;EAE/C,gBAAgB,CAAC,CAAC,CAAC;;sBAEC,gBAAgB;GACnC,CAAC,CAAC,CAAC,EAAE;CACP,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { BOUNCE_CURVE, PRESS_SCALE_PRIMARY, PRESS_SCALE_SUBTLE, pressPrimary, pressSubtle, pressPrimaryScale, pressSubtleScale, } from './press.js';
|
|
2
|
+
export { useAnimatedAction } from './use-animated-action.js';
|
|
3
|
+
export { actionSheetContainer, actionSheetList, actionSheetRow, } from './action-sheet.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { BOUNCE_CURVE, PRESS_SCALE_PRIMARY, PRESS_SCALE_SUBTLE, pressPrimary, pressSubtle, pressPrimaryScale, pressSubtleScale, } from './press.js';
|
|
2
|
+
export { useAnimatedAction } from './use-animated-action.js';
|
|
3
|
+
export { actionSheetContainer, actionSheetList, actionSheetRow, } from './action-sheet.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"}
|
package/dist/press.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Press-feedback CSS primitives — the generic press language for Kang consumers.
|
|
3
|
+
*
|
|
4
|
+
* CSS-first: every helper returns a plain CSS string (no styled-components or
|
|
5
|
+
* other CSS-in-JS dependency). Interpolate the result into whatever template
|
|
6
|
+
* your styling layer uses, e.g. styled-components:
|
|
7
|
+
*
|
|
8
|
+
* const Button = styled.button`
|
|
9
|
+
* ${pressPrimary()}
|
|
10
|
+
* `;
|
|
11
|
+
*
|
|
12
|
+
* Two tiers:
|
|
13
|
+
* - pressPrimary (scale 0.95): discrete action buttons — CTAs, icon buttons,
|
|
14
|
+
* confirm/cancel buttons, nav controls.
|
|
15
|
+
* - pressSubtle (scale 0.97): large tappable surfaces — tiles, cards, list
|
|
16
|
+
* rows, picker options, tabs.
|
|
17
|
+
*
|
|
18
|
+
* Physics: press down fast (60ms, ease-out); release with a bouncy spring-back
|
|
19
|
+
* (300ms, cubic-bezier overshooting ~6%) — a rubber-band feel without JS spring
|
|
20
|
+
* physics.
|
|
21
|
+
*
|
|
22
|
+
* Each helper owns the `transition` declaration in both rest and pressed
|
|
23
|
+
* states. If the element transitions other properties (background, color,
|
|
24
|
+
* opacity...), pass them via `extraTransition` instead of declaring a second
|
|
25
|
+
* `transition` — a separate declaration would override this one.
|
|
26
|
+
*
|
|
27
|
+
* The *Scale variants animate the CSS `scale` property instead of `transform`,
|
|
28
|
+
* for elements whose `transform` is already controlled elsewhere (e.g. a JS
|
|
29
|
+
* spring).
|
|
30
|
+
*/
|
|
31
|
+
export declare const BOUNCE_CURVE = "cubic-bezier(0.34, 1.56, 0.64, 1)";
|
|
32
|
+
export declare const PRESS_SCALE_PRIMARY = 0.95;
|
|
33
|
+
export declare const PRESS_SCALE_SUBTLE = 0.97;
|
|
34
|
+
/** Action buttons: CTAs, icon buttons, confirm/cancel. */
|
|
35
|
+
export declare const pressPrimary: (extraTransition?: string) => string;
|
|
36
|
+
/** Tappable surfaces: tiles, cards, rows, tabs. */
|
|
37
|
+
export declare const pressSubtle: (extraTransition?: string) => string;
|
|
38
|
+
/** pressPrimary for elements whose `transform` is controlled elsewhere (uses CSS `scale`). */
|
|
39
|
+
export declare const pressPrimaryScale: (extraTransition?: string) => string;
|
|
40
|
+
/** pressSubtle for elements whose `transform` is controlled elsewhere (uses CSS `scale`). */
|
|
41
|
+
export declare const pressSubtleScale: (extraTransition?: string) => string;
|
|
42
|
+
//# sourceMappingURL=press.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"press.d.ts","sourceRoot":"","sources":["../src/press.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,eAAO,MAAM,YAAY,sCAAsC,CAAC;AAEhE,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAwBvC,0DAA0D;AAC1D,eAAO,MAAM,YAAY,qBAAsB,MAAM,KAAG,MACN,CAAC;AAEnD,mDAAmD;AACnD,eAAO,MAAM,WAAW,qBAAsB,MAAM,KAAG,MACN,CAAC;AAElD,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,qBAAsB,MAAM,KAAG,MACN,CAAC;AAExD,6FAA6F;AAC7F,eAAO,MAAM,gBAAgB,qBAAsB,MAAM,KAAG,MACN,CAAC"}
|
package/dist/press.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Press-feedback CSS primitives — the generic press language for Kang consumers.
|
|
3
|
+
*
|
|
4
|
+
* CSS-first: every helper returns a plain CSS string (no styled-components or
|
|
5
|
+
* other CSS-in-JS dependency). Interpolate the result into whatever template
|
|
6
|
+
* your styling layer uses, e.g. styled-components:
|
|
7
|
+
*
|
|
8
|
+
* const Button = styled.button`
|
|
9
|
+
* ${pressPrimary()}
|
|
10
|
+
* `;
|
|
11
|
+
*
|
|
12
|
+
* Two tiers:
|
|
13
|
+
* - pressPrimary (scale 0.95): discrete action buttons — CTAs, icon buttons,
|
|
14
|
+
* confirm/cancel buttons, nav controls.
|
|
15
|
+
* - pressSubtle (scale 0.97): large tappable surfaces — tiles, cards, list
|
|
16
|
+
* rows, picker options, tabs.
|
|
17
|
+
*
|
|
18
|
+
* Physics: press down fast (60ms, ease-out); release with a bouncy spring-back
|
|
19
|
+
* (300ms, cubic-bezier overshooting ~6%) — a rubber-band feel without JS spring
|
|
20
|
+
* physics.
|
|
21
|
+
*
|
|
22
|
+
* Each helper owns the `transition` declaration in both rest and pressed
|
|
23
|
+
* states. If the element transitions other properties (background, color,
|
|
24
|
+
* opacity...), pass them via `extraTransition` instead of declaring a second
|
|
25
|
+
* `transition` — a separate declaration would override this one.
|
|
26
|
+
*
|
|
27
|
+
* The *Scale variants animate the CSS `scale` property instead of `transform`,
|
|
28
|
+
* for elements whose `transform` is already controlled elsewhere (e.g. a JS
|
|
29
|
+
* spring).
|
|
30
|
+
*/
|
|
31
|
+
export const BOUNCE_CURVE = 'cubic-bezier(0.34, 1.56, 0.64, 1)';
|
|
32
|
+
export const PRESS_SCALE_PRIMARY = 0.95;
|
|
33
|
+
export const PRESS_SCALE_SUBTLE = 0.97;
|
|
34
|
+
const transitionFor = (property, duration, easing, extra) => `transition: ${property} ${duration} ${easing}${extra ? `, ${extra}` : ''};`;
|
|
35
|
+
const springPress = (scaleValue, extraTransition) => `
|
|
36
|
+
${transitionFor('transform', '0.3s', BOUNCE_CURVE, extraTransition)}
|
|
37
|
+
will-change: transform;
|
|
38
|
+
|
|
39
|
+
&:active {
|
|
40
|
+
transform: scale(${scaleValue});
|
|
41
|
+
${transitionFor('transform', '0.06s', 'ease-out', extraTransition)}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
const springPressScale = (scaleValue, extraTransition) => `
|
|
45
|
+
${transitionFor('scale', '0.3s', BOUNCE_CURVE, extraTransition)}
|
|
46
|
+
|
|
47
|
+
&:active {
|
|
48
|
+
scale: ${scaleValue};
|
|
49
|
+
${transitionFor('scale', '0.06s', 'ease-out', extraTransition)}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
/** Action buttons: CTAs, icon buttons, confirm/cancel. */
|
|
53
|
+
export const pressPrimary = (extraTransition) => springPress(PRESS_SCALE_PRIMARY, extraTransition);
|
|
54
|
+
/** Tappable surfaces: tiles, cards, rows, tabs. */
|
|
55
|
+
export const pressSubtle = (extraTransition) => springPress(PRESS_SCALE_SUBTLE, extraTransition);
|
|
56
|
+
/** pressPrimary for elements whose `transform` is controlled elsewhere (uses CSS `scale`). */
|
|
57
|
+
export const pressPrimaryScale = (extraTransition) => springPressScale(PRESS_SCALE_PRIMARY, extraTransition);
|
|
58
|
+
/** pressSubtle for elements whose `transform` is controlled elsewhere (uses CSS `scale`). */
|
|
59
|
+
export const pressSubtleScale = (extraTransition) => springPressScale(PRESS_SCALE_SUBTLE, extraTransition);
|
|
60
|
+
//# sourceMappingURL=press.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"press.js","sourceRoot":"","sources":["../src/press.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEhE,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,aAAa,GAAG,CAAC,QAAgB,EAAE,QAAgB,EAAE,MAAc,EAAE,KAAc,EAAU,EAAE,CACpG,eAAe,QAAQ,IAAI,QAAQ,IAAI,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;AAE9E,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAE,eAAwB,EAAU,EAAE,CAAC;GAC3E,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC;;;;qBAI/C,UAAU;IAC3B,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC;;CAEnE,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,UAAkB,EAAE,eAAwB,EAAU,EAAE,CAAC;GAChF,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC;;;WAGrD,UAAU;IACjB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,CAAC;;CAE/D,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,eAAwB,EAAU,EAAE,CAChE,WAAW,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;AAEnD,mDAAmD;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,eAAwB,EAAU,EAAE,CAC/D,WAAW,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC;AAElD,8FAA8F;AAC9F,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,eAAwB,EAAU,EAAE,CACrE,gBAAgB,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;AAExD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,eAAwB,EAAU,EAAE,CACpE,gBAAgB,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-animated-action.d.ts","sourceRoot":"","sources":["../src/use-animated-action.ts"],"names":[],"mappings":"AAaA,wBAAgB,iBAAiB,CAAC,OAAO,SAAmB,cAY/C,MAAM,IAAI,UAWtB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useCallback, useRef, useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Delays an action callback so that visual feedback (ripple, press animation)
|
|
4
|
+
* has time to be perceived before the UI transitions away.
|
|
5
|
+
*
|
|
6
|
+
* Uses 180ms by default — long enough to see the ripple start expanding,
|
|
7
|
+
* short enough to feel responsive (under the 200ms "instant" threshold).
|
|
8
|
+
*
|
|
9
|
+
* All pending timeouts are cleared on unmount.
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_DELAY_MS = 180;
|
|
12
|
+
export function useAnimatedAction(delayMs = DEFAULT_DELAY_MS) {
|
|
13
|
+
const timeoutsRef = useRef(new Set());
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
return () => {
|
|
16
|
+
for (const id of timeoutsRef.current) {
|
|
17
|
+
clearTimeout(id);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}, []);
|
|
21
|
+
const act = useCallback((callback) => {
|
|
22
|
+
const id = setTimeout(() => {
|
|
23
|
+
timeoutsRef.current.delete(id);
|
|
24
|
+
callback();
|
|
25
|
+
}, delayMs);
|
|
26
|
+
timeoutsRef.current.add(id);
|
|
27
|
+
}, [delayMs]);
|
|
28
|
+
return act;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=use-animated-action.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-animated-action.js","sourceRoot":"","sources":["../src/use-animated-action.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,MAAM,UAAU,iBAAiB,CAAC,OAAO,GAAG,gBAAgB;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAqC,IAAI,GAAG,EAAE,CAAC,CAAC;IAE1E,SAAS,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,EAAE;YACX,KAAK,MAAM,EAAE,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACtC,YAAY,CAAC,EAAE,CAAC,CAAC;YAClB,CAAC;QACF,CAAC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,GAAG,GAAG,WAAW,CACtB,CAAC,QAAoB,EAAE,EAAE;QACxB,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC/B,QAAQ,EAAE,CAAC;QACZ,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC,EACD,CAAC,OAAO,CAAC,CACT,CAAC;IAEF,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,43 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kang-components",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Generic, domain-free React UI primitives (CSS-first press feedback, delayed-action hook).",
|
|
4
5
|
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/LoganConnor44/kang-components.git"
|
|
10
|
+
},
|
|
5
11
|
"files": [
|
|
6
12
|
"dist"
|
|
7
13
|
],
|
|
8
|
-
"main": "./dist/
|
|
9
|
-
"module": "./dist/
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
10
17
|
"exports": {
|
|
11
18
|
".": {
|
|
12
|
-
"
|
|
13
|
-
"
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js"
|
|
14
21
|
}
|
|
15
22
|
},
|
|
23
|
+
"sideEffects": false,
|
|
16
24
|
"scripts": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"build": "tsc -b && vite build",
|
|
20
|
-
"lint": "eslint .",
|
|
21
|
-
"preview": "vite preview",
|
|
22
|
-
"prepublish": "npm run build",
|
|
23
|
-
"publish": "npm publish"
|
|
25
|
+
"build": "tsc -p tsconfig.build.json",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
24
27
|
},
|
|
25
|
-
"
|
|
26
|
-
"react": "
|
|
27
|
-
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"react": {
|
|
33
|
+
"optional": true
|
|
34
|
+
}
|
|
28
35
|
},
|
|
29
36
|
"devDependencies": {
|
|
30
|
-
"@eslint/js": "^9.17.0",
|
|
31
|
-
"@types/node": "^22.10.5",
|
|
32
37
|
"@types/react": "^18.3.18",
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"eslint": "^9.17.0",
|
|
36
|
-
"eslint-plugin-react-hooks": "^5.0.0",
|
|
37
|
-
"eslint-plugin-react-refresh": "^0.4.16",
|
|
38
|
-
"globals": "^15.14.0",
|
|
39
|
-
"typescript": "~5.6.2",
|
|
40
|
-
"typescript-eslint": "^8.18.2",
|
|
41
|
-
"vite": "^6.0.5"
|
|
38
|
+
"react": "^18.3.1",
|
|
39
|
+
"typescript": "~5.6.2"
|
|
42
40
|
}
|
|
43
41
|
}
|
package/dist/kang-components.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(function(e,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("react/jsx-runtime")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime"],t):(e=typeof globalThis<"u"?globalThis:e||self,t(e.KangComponents={},e["react/jsx-runtime"]))})(this,function(e,t){"use strict";const n=({children:i})=>t.jsx("button",{children:i});e.Test=n,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
|
package/dist/vite.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|