@easemate/web-kit 0.1.4 → 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 +360 -168
- package/build/components/code/index.cjs +3 -3
- package/build/components/code/index.js +3 -3
- package/build/components/curve/canvas-controls.cjs +3 -3
- package/build/components/curve/canvas-controls.js +3 -3
- package/build/components/curve/canvas.cjs +4 -4
- package/build/components/curve/canvas.js +4 -4
- package/build/components/curve/controls.cjs +6 -6
- package/build/components/curve/controls.d.cts +4 -4
- package/build/components/curve/controls.d.ts +4 -4
- package/build/components/curve/controls.js +6 -6
- package/build/components/curve/index.cjs +3 -3
- package/build/components/curve/index.d.cts +1 -1
- package/build/components/curve/index.d.ts +1 -1
- package/build/components/curve/index.js +3 -3
- package/build/components/curve/output.cjs +3 -3
- package/build/components/curve/output.d.cts +1 -1
- package/build/components/curve/output.d.ts +1 -1
- package/build/components/curve/output.js +3 -3
- package/build/components/curve/toolbar.cjs +7 -7
- package/build/components/curve/toolbar.d.cts +4 -4
- package/build/components/curve/toolbar.d.ts +4 -4
- package/build/components/curve/toolbar.js +7 -7
- package/build/decorators/OutsideClick.cjs +2 -2
- package/build/decorators/OutsideClick.d.cts +2 -2
- package/build/decorators/OutsideClick.d.ts +2 -2
- package/build/decorators/OutsideClick.js +2 -2
- package/build/elements/button/index.cjs +2 -2
- package/build/elements/button/index.js +2 -2
- package/build/elements/checkbox/index.cjs +4 -4
- package/build/elements/checkbox/index.js +4 -4
- package/build/elements/color/index.cjs +4 -4
- package/build/elements/color/index.d.cts +1 -1
- package/build/elements/color/index.d.ts +1 -1
- package/build/elements/color/index.js +4 -4
- package/build/elements/color/picker.cjs +4 -4
- package/build/elements/color/picker.js +4 -4
- package/build/elements/dropdown/index.cjs +4 -4
- package/build/elements/dropdown/index.d.cts +1 -1
- package/build/elements/dropdown/index.d.ts +1 -1
- package/build/elements/dropdown/index.js +4 -4
- package/build/elements/field/index.cjs +2 -2
- package/build/elements/field/index.js +2 -2
- package/build/elements/icons/animation/chevron.cjs +2 -2
- package/build/elements/icons/animation/chevron.js +2 -2
- package/build/elements/icons/animation/clear.cjs +1 -1
- package/build/elements/icons/animation/clear.js +1 -1
- package/build/elements/icons/animation/grid.cjs +2 -2
- package/build/elements/icons/animation/grid.js +2 -2
- package/build/elements/icons/animation/loading.cjs +1 -1
- package/build/elements/icons/animation/loading.js +1 -1
- package/build/elements/icons/animation/snap.cjs +2 -2
- package/build/elements/icons/animation/snap.js +2 -2
- package/build/elements/icons/interface/anchor-add.cjs +1 -1
- package/build/elements/icons/interface/anchor-add.js +1 -1
- package/build/elements/icons/interface/anchor-remove.cjs +1 -1
- package/build/elements/icons/interface/anchor-remove.js +1 -1
- package/build/elements/icons/interface/arrow-up.cjs +1 -1
- package/build/elements/icons/interface/arrow-up.js +1 -1
- package/build/elements/icons/interface/arrows-vertical.cjs +1 -1
- package/build/elements/icons/interface/arrows-vertical.js +1 -1
- package/build/elements/icons/interface/bezier-angle.cjs +1 -1
- package/build/elements/icons/interface/bezier-angle.js +1 -1
- package/build/elements/icons/interface/bezier-distribute.cjs +1 -1
- package/build/elements/icons/interface/bezier-distribute.js +1 -1
- package/build/elements/icons/interface/bezier-length.cjs +1 -1
- package/build/elements/icons/interface/bezier-length.js +1 -1
- package/build/elements/icons/interface/bezier-mirror.cjs +1 -1
- package/build/elements/icons/interface/bezier-mirror.js +1 -1
- package/build/elements/icons/interface/bezier.cjs +1 -1
- package/build/elements/icons/interface/bezier.js +1 -1
- package/build/elements/icons/interface/check.cjs +1 -1
- package/build/elements/icons/interface/check.js +1 -1
- package/build/elements/icons/interface/circle-arrow-left.cjs +1 -1
- package/build/elements/icons/interface/circle-arrow-left.js +1 -1
- package/build/elements/icons/interface/circle-arrow-right.cjs +1 -1
- package/build/elements/icons/interface/circle-arrow-right.js +1 -1
- package/build/elements/icons/interface/code.cjs +1 -1
- package/build/elements/icons/interface/code.js +1 -1
- package/build/elements/icons/interface/dots.cjs +1 -1
- package/build/elements/icons/interface/dots.js +1 -1
- package/build/elements/icons/interface/mention.cjs +1 -1
- package/build/elements/icons/interface/mention.js +1 -1
- package/build/elements/icons/interface/minus.cjs +1 -1
- package/build/elements/icons/interface/minus.js +1 -1
- package/build/elements/icons/interface/picker.cjs +1 -1
- package/build/elements/icons/interface/picker.js +1 -1
- package/build/elements/icons/interface/plus.cjs +1 -1
- package/build/elements/icons/interface/plus.js +1 -1
- package/build/elements/icons/interface/settings.cjs +1 -1
- package/build/elements/icons/interface/settings.js +1 -1
- package/build/elements/index.cjs +5 -2
- package/build/elements/index.d.cts +2 -1
- package/build/elements/index.d.ts +2 -1
- package/build/elements/index.js +2 -1
- package/build/elements/input/index.cjs +4 -4
- package/build/elements/input/index.js +4 -4
- package/build/elements/logo/index.cjs +2 -2
- package/build/elements/logo/index.js +2 -2
- package/build/elements/monitor/fps.cjs +3 -3
- package/build/elements/monitor/fps.js +3 -3
- package/build/elements/monitor/index.cjs +4 -4
- package/build/elements/monitor/index.js +4 -4
- package/build/elements/number/index.cjs +4 -4
- package/build/elements/number/index.js +4 -4
- package/build/elements/origin/index.cjs +4 -4
- package/build/elements/origin/index.js +4 -4
- package/build/elements/panel/index.cjs +496 -0
- package/build/elements/panel/index.d.cts +67 -0
- package/build/elements/panel/index.d.ts +67 -0
- package/build/elements/panel/index.js +492 -0
- package/build/elements/popover/index.cjs +2 -2
- package/build/elements/popover/index.js +2 -2
- package/build/elements/radio/index.cjs +3 -3
- package/build/elements/radio/index.js +3 -3
- package/build/elements/radio/input.cjs +4 -4
- package/build/elements/radio/input.js +4 -4
- package/build/elements/slider/index.cjs +4 -4
- package/build/elements/slider/index.js +4 -4
- package/build/elements/state/index.cjs +61 -468
- package/build/elements/state/index.d.cts +34 -25
- package/build/elements/state/index.d.ts +34 -25
- package/build/elements/state/index.js +63 -470
- package/build/elements/toggle/index.cjs +4 -4
- package/build/elements/toggle/index.js +4 -4
- package/build/elements/tooltip/index.cjs +4 -4
- package/build/elements/tooltip/index.d.cts +1 -1
- package/build/elements/tooltip/index.d.ts +1 -1
- package/build/elements/tooltip/index.js +4 -4
- package/build/internal/component-loaders.cjs +2 -0
- package/build/internal/component-loaders.d.cts +2 -2
- package/build/internal/component-loaders.d.ts +2 -2
- package/build/internal/component-loaders.js +2 -0
- package/build/react/events.cjs +25 -0
- package/build/react/events.d.cts +39 -0
- package/build/react/events.d.ts +39 -0
- package/build/react/events.js +22 -0
- package/build/react/index.cjs +19 -0
- package/build/react/index.d.cts +13 -0
- package/build/react/index.d.ts +13 -0
- package/build/react/index.js +12 -0
- package/build/react/provider.cjs +134 -0
- package/build/react/provider.d.cts +81 -0
- package/build/react/provider.d.ts +81 -0
- package/build/react/provider.js +98 -0
- package/build/react/types.cjs +8 -0
- package/build/react/types.d.cts +55 -0
- package/build/react/types.d.ts +55 -0
- package/build/react/types.js +7 -0
- package/build/react/use-ease-state.cjs +129 -0
- package/build/react/use-ease-state.d.cts +95 -0
- package/build/react/use-ease-state.d.ts +95 -0
- package/build/react/use-ease-state.js +126 -0
- package/build/react/use-web-kit.cjs +150 -0
- package/build/react/use-web-kit.d.cts +80 -0
- package/build/react/use-web-kit.d.ts +80 -0
- package/build/react/use-web-kit.js +114 -0
- package/build/register.cjs +1 -0
- package/build/register.d.cts +1 -0
- package/build/register.d.ts +1 -0
- package/build/register.js +1 -0
- package/package.json +16 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context provider for @easemate/web-kit
|
|
3
|
+
*
|
|
4
|
+
* This module provides a simple way to initialize the web kit in a React context.
|
|
5
|
+
* For simpler use cases, consider using `initWebKit()` directly in a useEffect.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Creates a WebKit provider and context hook.
|
|
9
|
+
*
|
|
10
|
+
* This function creates a React context and provider component
|
|
11
|
+
* that initializes the web kit and provides access to its state.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* // providers.tsx
|
|
16
|
+
* 'use client';
|
|
17
|
+
*
|
|
18
|
+
* import * as React from '../react';
|
|
19
|
+
* import { createWebKitProvider } from '@easemate/web-kit/react';
|
|
20
|
+
*
|
|
21
|
+
* const { WebKitProvider, useWebKitContext } = createWebKitProvider(React);
|
|
22
|
+
*
|
|
23
|
+
* export { WebKitProvider, useWebKitContext };
|
|
24
|
+
*
|
|
25
|
+
* // layout.tsx
|
|
26
|
+
* import { WebKitProvider } from './providers';
|
|
27
|
+
*
|
|
28
|
+
* export default function Layout({ children }) {
|
|
29
|
+
* return (
|
|
30
|
+
* <WebKitProvider options={{ theme: 'default', styles: 'main' }}>
|
|
31
|
+
* {children}
|
|
32
|
+
* </WebKitProvider>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function createWebKitProvider(React) {
|
|
38
|
+
const defaultValue = {
|
|
39
|
+
ready: false,
|
|
40
|
+
theme: undefined
|
|
41
|
+
};
|
|
42
|
+
const WebKitContext = React.createContext(defaultValue);
|
|
43
|
+
function WebKitProvider(props) {
|
|
44
|
+
const { options = {}, immediate = true, children } = props;
|
|
45
|
+
const isSSR = typeof window === 'undefined';
|
|
46
|
+
const { useState, useEffect, useMemo, createElement } = React;
|
|
47
|
+
const [ready, setReady] = useState(false);
|
|
48
|
+
const [controller, setController] = useState(null);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
// Skip initialization on SSR
|
|
51
|
+
if (isSSR) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
let isMounted = true;
|
|
55
|
+
const initialize = async () => {
|
|
56
|
+
const { initWebKit } = await import('../init');
|
|
57
|
+
const ctrl = initWebKit(options);
|
|
58
|
+
if (isMounted) {
|
|
59
|
+
setController(ctrl);
|
|
60
|
+
}
|
|
61
|
+
await ctrl.ready;
|
|
62
|
+
if (isMounted) {
|
|
63
|
+
setReady(true);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
initialize();
|
|
67
|
+
return () => {
|
|
68
|
+
isMounted = false;
|
|
69
|
+
controller?.dispose();
|
|
70
|
+
return undefined;
|
|
71
|
+
};
|
|
72
|
+
}, []);
|
|
73
|
+
const value = useMemo(() => {
|
|
74
|
+
return {
|
|
75
|
+
ready,
|
|
76
|
+
theme: controller?.theme
|
|
77
|
+
};
|
|
78
|
+
}, [ready, controller]);
|
|
79
|
+
// On SSR, just render children directly
|
|
80
|
+
if (isSSR) {
|
|
81
|
+
return children;
|
|
82
|
+
}
|
|
83
|
+
// Don't render children until ready if immediate is false
|
|
84
|
+
if (!immediate && !ready) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return createElement(WebKitContext.Provider, { value }, children);
|
|
88
|
+
}
|
|
89
|
+
function useWebKitContext() {
|
|
90
|
+
const context = React.useContext(WebKitContext);
|
|
91
|
+
// On SSR, context will be the default value anyway
|
|
92
|
+
return context;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
WebKitProvider,
|
|
96
|
+
useWebKitContext
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React type definitions for @easemate/web-kit
|
|
4
|
+
*
|
|
5
|
+
* These types are provided for consumers using React/Next.js with this library.
|
|
6
|
+
* React is NOT a dependency of this package - these are interface definitions only.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React type definitions for @easemate/web-kit
|
|
3
|
+
*
|
|
4
|
+
* These types are provided for consumers using React/Next.js with this library.
|
|
5
|
+
* React is NOT a dependency of this package - these are interface definitions only.
|
|
6
|
+
*/
|
|
7
|
+
import type { TabChangeEventDetail } from '../elements/panel';
|
|
8
|
+
import type { StateChangeEventDetail } from '../elements/state';
|
|
9
|
+
/**
|
|
10
|
+
* Ref type for the ease-state web component
|
|
11
|
+
*/
|
|
12
|
+
export interface EaseStateRef extends HTMLElement {
|
|
13
|
+
/** Get the current state object */
|
|
14
|
+
readonly state: Record<string, unknown>;
|
|
15
|
+
/** Get a specific control value */
|
|
16
|
+
get(name: string): unknown;
|
|
17
|
+
/** Set a specific control value */
|
|
18
|
+
set(name: string, value: unknown): void;
|
|
19
|
+
/** Subscribe to state changes */
|
|
20
|
+
subscribe(callback: (value: unknown, name: string) => void): {
|
|
21
|
+
unsubscribe: () => void;
|
|
22
|
+
};
|
|
23
|
+
subscribe(name: string, callback: (value: unknown, name: string) => void): {
|
|
24
|
+
unsubscribe: () => void;
|
|
25
|
+
};
|
|
26
|
+
/** Reset all controls to initial values */
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ref type for the ease-panel web component
|
|
31
|
+
*/
|
|
32
|
+
export interface EasePanelRef extends HTMLElement {
|
|
33
|
+
/** Current active tab index */
|
|
34
|
+
activeTab: number;
|
|
35
|
+
/** Get the tab configuration */
|
|
36
|
+
readonly tabs: ReadonlyArray<{
|
|
37
|
+
id: string;
|
|
38
|
+
label: string;
|
|
39
|
+
}>;
|
|
40
|
+
/** Switch to a specific tab */
|
|
41
|
+
setTab(index: number): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Event detail types re-exported for React usage
|
|
45
|
+
*/
|
|
46
|
+
export type { StateChangeEventDetail, TabChangeEventDetail };
|
|
47
|
+
/**
|
|
48
|
+
* Generic control element interface
|
|
49
|
+
*/
|
|
50
|
+
export interface EaseControlElement extends HTMLElement {
|
|
51
|
+
name?: string;
|
|
52
|
+
value?: unknown;
|
|
53
|
+
checked?: boolean;
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React type definitions for @easemate/web-kit
|
|
3
|
+
*
|
|
4
|
+
* These types are provided for consumers using React/Next.js with this library.
|
|
5
|
+
* React is NOT a dependency of this package - these are interface definitions only.
|
|
6
|
+
*/
|
|
7
|
+
import type { TabChangeEventDetail } from '../elements/panel';
|
|
8
|
+
import type { StateChangeEventDetail } from '../elements/state';
|
|
9
|
+
/**
|
|
10
|
+
* Ref type for the ease-state web component
|
|
11
|
+
*/
|
|
12
|
+
export interface EaseStateRef extends HTMLElement {
|
|
13
|
+
/** Get the current state object */
|
|
14
|
+
readonly state: Record<string, unknown>;
|
|
15
|
+
/** Get a specific control value */
|
|
16
|
+
get(name: string): unknown;
|
|
17
|
+
/** Set a specific control value */
|
|
18
|
+
set(name: string, value: unknown): void;
|
|
19
|
+
/** Subscribe to state changes */
|
|
20
|
+
subscribe(callback: (value: unknown, name: string) => void): {
|
|
21
|
+
unsubscribe: () => void;
|
|
22
|
+
};
|
|
23
|
+
subscribe(name: string, callback: (value: unknown, name: string) => void): {
|
|
24
|
+
unsubscribe: () => void;
|
|
25
|
+
};
|
|
26
|
+
/** Reset all controls to initial values */
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ref type for the ease-panel web component
|
|
31
|
+
*/
|
|
32
|
+
export interface EasePanelRef extends HTMLElement {
|
|
33
|
+
/** Current active tab index */
|
|
34
|
+
activeTab: number;
|
|
35
|
+
/** Get the tab configuration */
|
|
36
|
+
readonly tabs: ReadonlyArray<{
|
|
37
|
+
id: string;
|
|
38
|
+
label: string;
|
|
39
|
+
}>;
|
|
40
|
+
/** Switch to a specific tab */
|
|
41
|
+
setTab(index: number): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Event detail types re-exported for React usage
|
|
45
|
+
*/
|
|
46
|
+
export type { StateChangeEventDetail, TabChangeEventDetail };
|
|
47
|
+
/**
|
|
48
|
+
* Generic control element interface
|
|
49
|
+
*/
|
|
50
|
+
export interface EaseControlElement extends HTMLElement {
|
|
51
|
+
name?: string;
|
|
52
|
+
value?: unknown;
|
|
53
|
+
checked?: boolean;
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* React hook for working with ease-state component
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useEaseState = useEaseState;
|
|
7
|
+
/**
|
|
8
|
+
* React hook for working with ease-state components.
|
|
9
|
+
*
|
|
10
|
+
* Provides a reactive state object and methods for interacting
|
|
11
|
+
* with the ease-state web component.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { useState, useCallback, useRef } from '../react';
|
|
16
|
+
* import { useEaseState } from '@easemate/web-kit/react';
|
|
17
|
+
*
|
|
18
|
+
* function AnimationControls() {
|
|
19
|
+
* const {
|
|
20
|
+
* stateRef,
|
|
21
|
+
* panelRef,
|
|
22
|
+
* state,
|
|
23
|
+
* set,
|
|
24
|
+
* reset
|
|
25
|
+
* } = useEaseState<{ duration: number; easing: string; loop: boolean }>(
|
|
26
|
+
* {
|
|
27
|
+
* onChange: ({ name, value }) => {
|
|
28
|
+
* console.log(`${name} changed to ${value}`);
|
|
29
|
+
* }
|
|
30
|
+
* },
|
|
31
|
+
* { useState, useCallback, useRef }
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* return (
|
|
35
|
+
* <ease-panel ref={panelRef}>
|
|
36
|
+
* <span slot="headline">Animation</span>
|
|
37
|
+
* <ease-state ref={stateRef}>
|
|
38
|
+
* <ease-field label="Duration">
|
|
39
|
+
* <ease-slider name="duration" value="1" min="0" max="5" />
|
|
40
|
+
* </ease-field>
|
|
41
|
+
* </ease-state>
|
|
42
|
+
* </ease-panel>
|
|
43
|
+
* );
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function useEaseState(options, hooks) {
|
|
48
|
+
const { useState, useCallback, useRef } = hooks;
|
|
49
|
+
const { initialState, onChange, onTabChange } = options;
|
|
50
|
+
const stateElementRef = useRef(null);
|
|
51
|
+
const panelElementRef = useRef(null);
|
|
52
|
+
const [state, setState] = useState((initialState ?? {}));
|
|
53
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
54
|
+
// Handle state changes
|
|
55
|
+
const handleStateChange = useCallback((e) => {
|
|
56
|
+
const customEvent = e;
|
|
57
|
+
const { name, value } = customEvent.detail;
|
|
58
|
+
setState((prev) => {
|
|
59
|
+
return { ...prev, [name]: value };
|
|
60
|
+
});
|
|
61
|
+
onChange?.(customEvent.detail);
|
|
62
|
+
}, [onChange]);
|
|
63
|
+
// Handle tab changes
|
|
64
|
+
const handleTabChange = useCallback((e) => {
|
|
65
|
+
const customEvent = e;
|
|
66
|
+
setActiveTab(customEvent.detail.index);
|
|
67
|
+
onTabChange?.(customEvent.detail);
|
|
68
|
+
}, [onTabChange]);
|
|
69
|
+
// Ref callback for the ease-state element
|
|
70
|
+
const stateRef = useCallback((element) => {
|
|
71
|
+
// Cleanup previous element
|
|
72
|
+
if (stateElementRef.current) {
|
|
73
|
+
stateElementRef.current.removeEventListener('state-change', handleStateChange);
|
|
74
|
+
}
|
|
75
|
+
stateElementRef.current = element;
|
|
76
|
+
if (element) {
|
|
77
|
+
// Add event listeners
|
|
78
|
+
element.addEventListener('state-change', handleStateChange);
|
|
79
|
+
// Set initial state values
|
|
80
|
+
if (initialState) {
|
|
81
|
+
for (const [name, value] of Object.entries(initialState)) {
|
|
82
|
+
element.set(name, value);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Sync current state from element
|
|
86
|
+
const currentState = element.state;
|
|
87
|
+
if (Object.keys(currentState).length > 0) {
|
|
88
|
+
setState(currentState);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, [handleStateChange, initialState]);
|
|
92
|
+
// Ref callback for the ease-panel element
|
|
93
|
+
const panelRef = useCallback((element) => {
|
|
94
|
+
// Cleanup previous element
|
|
95
|
+
if (panelElementRef.current) {
|
|
96
|
+
panelElementRef.current.removeEventListener('tab-change', handleTabChange);
|
|
97
|
+
}
|
|
98
|
+
panelElementRef.current = element;
|
|
99
|
+
if (element) {
|
|
100
|
+
// Add event listeners
|
|
101
|
+
element.addEventListener('tab-change', handleTabChange);
|
|
102
|
+
setActiveTab(element.activeTab);
|
|
103
|
+
}
|
|
104
|
+
}, [handleTabChange]);
|
|
105
|
+
// Get a specific value
|
|
106
|
+
const get = useCallback((name) => state[name], [state]);
|
|
107
|
+
// Set a specific value
|
|
108
|
+
const set = useCallback((name, value) => {
|
|
109
|
+
stateElementRef.current?.set(name, value);
|
|
110
|
+
}, []);
|
|
111
|
+
// Reset all values
|
|
112
|
+
const reset = useCallback(() => {
|
|
113
|
+
stateElementRef.current?.reset();
|
|
114
|
+
}, []);
|
|
115
|
+
// Set active tab
|
|
116
|
+
const setTab = useCallback((index) => {
|
|
117
|
+
panelElementRef.current?.setTab(index);
|
|
118
|
+
}, []);
|
|
119
|
+
return {
|
|
120
|
+
stateRef,
|
|
121
|
+
panelRef,
|
|
122
|
+
state,
|
|
123
|
+
get,
|
|
124
|
+
set,
|
|
125
|
+
reset,
|
|
126
|
+
setTab,
|
|
127
|
+
activeTab
|
|
128
|
+
};
|
|
129
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for working with ease-state component
|
|
3
|
+
*/
|
|
4
|
+
import type { EasePanelRef, EaseStateRef, StateChangeEventDetail, TabChangeEventDetail } from "./types.cjs";
|
|
5
|
+
/**
|
|
6
|
+
* Options for useEaseState hook
|
|
7
|
+
*/
|
|
8
|
+
export interface UseEaseStateOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Initial state values to set when the component mounts
|
|
11
|
+
*/
|
|
12
|
+
initialState?: Record<string, unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* Callback fired when any control value changes
|
|
15
|
+
*/
|
|
16
|
+
onChange?: (detail: StateChangeEventDetail) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Callback fired when the active tab changes (requires ease-panel)
|
|
19
|
+
*/
|
|
20
|
+
onTabChange?: (detail: TabChangeEventDetail) => void;
|
|
21
|
+
}
|
|
22
|
+
type AnyFunction = (...args: any[]) => any;
|
|
23
|
+
/**
|
|
24
|
+
* React hooks interface - compatible with React's hook signatures
|
|
25
|
+
*/
|
|
26
|
+
export interface ReactHooksLike {
|
|
27
|
+
useState: <S>(initial: S) => [S, (value: S | ((prev: S) => S)) => void];
|
|
28
|
+
useCallback: <F extends AnyFunction>(callback: F, deps: unknown[]) => F;
|
|
29
|
+
useRef: <R>(initial: R) => {
|
|
30
|
+
current: R;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Return type for useEaseState hook
|
|
35
|
+
*/
|
|
36
|
+
export interface UseEaseStateReturn<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
37
|
+
/** Ref callback to attach to the ease-state element */
|
|
38
|
+
stateRef: (element: EaseStateRef | null) => void;
|
|
39
|
+
/** Ref callback to attach to the ease-panel element (optional) */
|
|
40
|
+
panelRef: (element: EasePanelRef | null) => void;
|
|
41
|
+
/** Current state values (reactive) */
|
|
42
|
+
state: T;
|
|
43
|
+
/** Get a specific control value */
|
|
44
|
+
get: <K extends keyof T>(name: K) => T[K] | undefined;
|
|
45
|
+
/** Set a specific control value */
|
|
46
|
+
set: <K extends keyof T>(name: K, value: T[K]) => void;
|
|
47
|
+
/** Reset all controls to initial values */
|
|
48
|
+
reset: () => void;
|
|
49
|
+
/** Switch to a specific tab (requires ease-panel) */
|
|
50
|
+
setTab: (index: number) => void;
|
|
51
|
+
/** Current active tab index (requires ease-panel) */
|
|
52
|
+
activeTab: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* React hook for working with ease-state components.
|
|
56
|
+
*
|
|
57
|
+
* Provides a reactive state object and methods for interacting
|
|
58
|
+
* with the ease-state web component.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* import { useState, useCallback, useRef } from '../react';
|
|
63
|
+
* import { useEaseState } from '@easemate/web-kit/react';
|
|
64
|
+
*
|
|
65
|
+
* function AnimationControls() {
|
|
66
|
+
* const {
|
|
67
|
+
* stateRef,
|
|
68
|
+
* panelRef,
|
|
69
|
+
* state,
|
|
70
|
+
* set,
|
|
71
|
+
* reset
|
|
72
|
+
* } = useEaseState<{ duration: number; easing: string; loop: boolean }>(
|
|
73
|
+
* {
|
|
74
|
+
* onChange: ({ name, value }) => {
|
|
75
|
+
* console.log(`${name} changed to ${value}`);
|
|
76
|
+
* }
|
|
77
|
+
* },
|
|
78
|
+
* { useState, useCallback, useRef }
|
|
79
|
+
* );
|
|
80
|
+
*
|
|
81
|
+
* return (
|
|
82
|
+
* <ease-panel ref={panelRef}>
|
|
83
|
+
* <span slot="headline">Animation</span>
|
|
84
|
+
* <ease-state ref={stateRef}>
|
|
85
|
+
* <ease-field label="Duration">
|
|
86
|
+
* <ease-slider name="duration" value="1" min="0" max="5" />
|
|
87
|
+
* </ease-field>
|
|
88
|
+
* </ease-state>
|
|
89
|
+
* </ease-panel>
|
|
90
|
+
* );
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function useEaseState<T extends Record<string, unknown> = Record<string, unknown>>(options: UseEaseStateOptions, hooks: ReactHooksLike): UseEaseStateReturn<T>;
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for working with ease-state component
|
|
3
|
+
*/
|
|
4
|
+
import type { EasePanelRef, EaseStateRef, StateChangeEventDetail, TabChangeEventDetail } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Options for useEaseState hook
|
|
7
|
+
*/
|
|
8
|
+
export interface UseEaseStateOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Initial state values to set when the component mounts
|
|
11
|
+
*/
|
|
12
|
+
initialState?: Record<string, unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* Callback fired when any control value changes
|
|
15
|
+
*/
|
|
16
|
+
onChange?: (detail: StateChangeEventDetail) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Callback fired when the active tab changes (requires ease-panel)
|
|
19
|
+
*/
|
|
20
|
+
onTabChange?: (detail: TabChangeEventDetail) => void;
|
|
21
|
+
}
|
|
22
|
+
type AnyFunction = (...args: any[]) => any;
|
|
23
|
+
/**
|
|
24
|
+
* React hooks interface - compatible with React's hook signatures
|
|
25
|
+
*/
|
|
26
|
+
export interface ReactHooksLike {
|
|
27
|
+
useState: <S>(initial: S) => [S, (value: S | ((prev: S) => S)) => void];
|
|
28
|
+
useCallback: <F extends AnyFunction>(callback: F, deps: unknown[]) => F;
|
|
29
|
+
useRef: <R>(initial: R) => {
|
|
30
|
+
current: R;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Return type for useEaseState hook
|
|
35
|
+
*/
|
|
36
|
+
export interface UseEaseStateReturn<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
37
|
+
/** Ref callback to attach to the ease-state element */
|
|
38
|
+
stateRef: (element: EaseStateRef | null) => void;
|
|
39
|
+
/** Ref callback to attach to the ease-panel element (optional) */
|
|
40
|
+
panelRef: (element: EasePanelRef | null) => void;
|
|
41
|
+
/** Current state values (reactive) */
|
|
42
|
+
state: T;
|
|
43
|
+
/** Get a specific control value */
|
|
44
|
+
get: <K extends keyof T>(name: K) => T[K] | undefined;
|
|
45
|
+
/** Set a specific control value */
|
|
46
|
+
set: <K extends keyof T>(name: K, value: T[K]) => void;
|
|
47
|
+
/** Reset all controls to initial values */
|
|
48
|
+
reset: () => void;
|
|
49
|
+
/** Switch to a specific tab (requires ease-panel) */
|
|
50
|
+
setTab: (index: number) => void;
|
|
51
|
+
/** Current active tab index (requires ease-panel) */
|
|
52
|
+
activeTab: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* React hook for working with ease-state components.
|
|
56
|
+
*
|
|
57
|
+
* Provides a reactive state object and methods for interacting
|
|
58
|
+
* with the ease-state web component.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* import { useState, useCallback, useRef } from '../react';
|
|
63
|
+
* import { useEaseState } from '@easemate/web-kit/react';
|
|
64
|
+
*
|
|
65
|
+
* function AnimationControls() {
|
|
66
|
+
* const {
|
|
67
|
+
* stateRef,
|
|
68
|
+
* panelRef,
|
|
69
|
+
* state,
|
|
70
|
+
* set,
|
|
71
|
+
* reset
|
|
72
|
+
* } = useEaseState<{ duration: number; easing: string; loop: boolean }>(
|
|
73
|
+
* {
|
|
74
|
+
* onChange: ({ name, value }) => {
|
|
75
|
+
* console.log(`${name} changed to ${value}`);
|
|
76
|
+
* }
|
|
77
|
+
* },
|
|
78
|
+
* { useState, useCallback, useRef }
|
|
79
|
+
* );
|
|
80
|
+
*
|
|
81
|
+
* return (
|
|
82
|
+
* <ease-panel ref={panelRef}>
|
|
83
|
+
* <span slot="headline">Animation</span>
|
|
84
|
+
* <ease-state ref={stateRef}>
|
|
85
|
+
* <ease-field label="Duration">
|
|
86
|
+
* <ease-slider name="duration" value="1" min="0" max="5" />
|
|
87
|
+
* </ease-field>
|
|
88
|
+
* </ease-state>
|
|
89
|
+
* </ease-panel>
|
|
90
|
+
* );
|
|
91
|
+
* }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function useEaseState<T extends Record<string, unknown> = Record<string, unknown>>(options: UseEaseStateOptions, hooks: ReactHooksLike): UseEaseStateReturn<T>;
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for working with ease-state component
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* React hook for working with ease-state components.
|
|
6
|
+
*
|
|
7
|
+
* Provides a reactive state object and methods for interacting
|
|
8
|
+
* with the ease-state web component.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { useState, useCallback, useRef } from '../react';
|
|
13
|
+
* import { useEaseState } from '@easemate/web-kit/react';
|
|
14
|
+
*
|
|
15
|
+
* function AnimationControls() {
|
|
16
|
+
* const {
|
|
17
|
+
* stateRef,
|
|
18
|
+
* panelRef,
|
|
19
|
+
* state,
|
|
20
|
+
* set,
|
|
21
|
+
* reset
|
|
22
|
+
* } = useEaseState<{ duration: number; easing: string; loop: boolean }>(
|
|
23
|
+
* {
|
|
24
|
+
* onChange: ({ name, value }) => {
|
|
25
|
+
* console.log(`${name} changed to ${value}`);
|
|
26
|
+
* }
|
|
27
|
+
* },
|
|
28
|
+
* { useState, useCallback, useRef }
|
|
29
|
+
* );
|
|
30
|
+
*
|
|
31
|
+
* return (
|
|
32
|
+
* <ease-panel ref={panelRef}>
|
|
33
|
+
* <span slot="headline">Animation</span>
|
|
34
|
+
* <ease-state ref={stateRef}>
|
|
35
|
+
* <ease-field label="Duration">
|
|
36
|
+
* <ease-slider name="duration" value="1" min="0" max="5" />
|
|
37
|
+
* </ease-field>
|
|
38
|
+
* </ease-state>
|
|
39
|
+
* </ease-panel>
|
|
40
|
+
* );
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function useEaseState(options, hooks) {
|
|
45
|
+
const { useState, useCallback, useRef } = hooks;
|
|
46
|
+
const { initialState, onChange, onTabChange } = options;
|
|
47
|
+
const stateElementRef = useRef(null);
|
|
48
|
+
const panelElementRef = useRef(null);
|
|
49
|
+
const [state, setState] = useState((initialState ?? {}));
|
|
50
|
+
const [activeTab, setActiveTab] = useState(0);
|
|
51
|
+
// Handle state changes
|
|
52
|
+
const handleStateChange = useCallback((e) => {
|
|
53
|
+
const customEvent = e;
|
|
54
|
+
const { name, value } = customEvent.detail;
|
|
55
|
+
setState((prev) => {
|
|
56
|
+
return { ...prev, [name]: value };
|
|
57
|
+
});
|
|
58
|
+
onChange?.(customEvent.detail);
|
|
59
|
+
}, [onChange]);
|
|
60
|
+
// Handle tab changes
|
|
61
|
+
const handleTabChange = useCallback((e) => {
|
|
62
|
+
const customEvent = e;
|
|
63
|
+
setActiveTab(customEvent.detail.index);
|
|
64
|
+
onTabChange?.(customEvent.detail);
|
|
65
|
+
}, [onTabChange]);
|
|
66
|
+
// Ref callback for the ease-state element
|
|
67
|
+
const stateRef = useCallback((element) => {
|
|
68
|
+
// Cleanup previous element
|
|
69
|
+
if (stateElementRef.current) {
|
|
70
|
+
stateElementRef.current.removeEventListener('state-change', handleStateChange);
|
|
71
|
+
}
|
|
72
|
+
stateElementRef.current = element;
|
|
73
|
+
if (element) {
|
|
74
|
+
// Add event listeners
|
|
75
|
+
element.addEventListener('state-change', handleStateChange);
|
|
76
|
+
// Set initial state values
|
|
77
|
+
if (initialState) {
|
|
78
|
+
for (const [name, value] of Object.entries(initialState)) {
|
|
79
|
+
element.set(name, value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Sync current state from element
|
|
83
|
+
const currentState = element.state;
|
|
84
|
+
if (Object.keys(currentState).length > 0) {
|
|
85
|
+
setState(currentState);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, [handleStateChange, initialState]);
|
|
89
|
+
// Ref callback for the ease-panel element
|
|
90
|
+
const panelRef = useCallback((element) => {
|
|
91
|
+
// Cleanup previous element
|
|
92
|
+
if (panelElementRef.current) {
|
|
93
|
+
panelElementRef.current.removeEventListener('tab-change', handleTabChange);
|
|
94
|
+
}
|
|
95
|
+
panelElementRef.current = element;
|
|
96
|
+
if (element) {
|
|
97
|
+
// Add event listeners
|
|
98
|
+
element.addEventListener('tab-change', handleTabChange);
|
|
99
|
+
setActiveTab(element.activeTab);
|
|
100
|
+
}
|
|
101
|
+
}, [handleTabChange]);
|
|
102
|
+
// Get a specific value
|
|
103
|
+
const get = useCallback((name) => state[name], [state]);
|
|
104
|
+
// Set a specific value
|
|
105
|
+
const set = useCallback((name, value) => {
|
|
106
|
+
stateElementRef.current?.set(name, value);
|
|
107
|
+
}, []);
|
|
108
|
+
// Reset all values
|
|
109
|
+
const reset = useCallback(() => {
|
|
110
|
+
stateElementRef.current?.reset();
|
|
111
|
+
}, []);
|
|
112
|
+
// Set active tab
|
|
113
|
+
const setTab = useCallback((index) => {
|
|
114
|
+
panelElementRef.current?.setTab(index);
|
|
115
|
+
}, []);
|
|
116
|
+
return {
|
|
117
|
+
stateRef,
|
|
118
|
+
panelRef,
|
|
119
|
+
state,
|
|
120
|
+
get,
|
|
121
|
+
set,
|
|
122
|
+
reset,
|
|
123
|
+
setTab,
|
|
124
|
+
activeTab
|
|
125
|
+
};
|
|
126
|
+
}
|