@seed-design/lynx-react 0.1.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/lib/_virtual/_rolldown/runtime.js +13 -0
- package/lib/components/ActionButton/ActionButton.d.ts +44 -0
- package/lib/components/ActionButton/ActionButton.d.ts.map +1 -0
- package/lib/components/ActionButton/ActionButton.jsx +158 -0
- package/lib/components/ActionButton/index.d.ts +2 -0
- package/lib/components/ActionButton/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts +87 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.jsx +150 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.d.ts +2 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.namespace.js +18 -0
- package/lib/components/BottomSheet/index.d.ts +3 -0
- package/lib/components/BottomSheet/index.d.ts.map +1 -0
- package/lib/components/Box/Box.d.ts +20 -0
- package/lib/components/Box/Box.d.ts.map +1 -0
- package/lib/components/Box/Box.jsx +14 -0
- package/lib/components/Box/index.d.ts +2 -0
- package/lib/components/Box/index.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.d.ts +35 -0
- package/lib/components/Checkbox/Checkbox.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.jsx +130 -0
- package/lib/components/Checkbox/Checkbox.namespace.d.ts +2 -0
- package/lib/components/Checkbox/Checkbox.namespace.d.ts.map +1 -0
- package/lib/components/Checkbox/Checkbox.namespace.js +12 -0
- package/lib/components/Checkbox/index.d.ts +3 -0
- package/lib/components/Checkbox/index.d.ts.map +1 -0
- package/lib/components/Icon/Icon.d.ts +37 -0
- package/lib/components/Icon/Icon.d.ts.map +1 -0
- package/lib/components/Icon/Icon.jsx +143 -0
- package/lib/components/Icon/index.d.ts +2 -0
- package/lib/components/Icon/index.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts +25 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.jsx +281 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.d.ts +2 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.d.ts.map +1 -0
- package/lib/components/ProgressCircle/ProgressCircle.namespace.js +9 -0
- package/lib/components/ProgressCircle/index.d.ts +3 -0
- package/lib/components/ProgressCircle/index.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.d.ts +34 -0
- package/lib/components/RadioGroup/RadioGroup.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.jsx +160 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.d.ts +2 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.namespace.js +12 -0
- package/lib/components/RadioGroup/index.d.ts +3 -0
- package/lib/components/RadioGroup/index.d.ts.map +1 -0
- package/lib/components/Stack/Stack.d.ts +33 -0
- package/lib/components/Stack/Stack.d.ts.map +1 -0
- package/lib/components/Stack/Stack.jsx +39 -0
- package/lib/components/Stack/index.d.ts +2 -0
- package/lib/components/Stack/index.d.ts.map +1 -0
- package/lib/components/Switch/Switch.d.ts +21 -0
- package/lib/components/Switch/Switch.d.ts.map +1 -0
- package/lib/components/Switch/Switch.jsx +101 -0
- package/lib/components/Switch/Switch.namespace.d.ts +2 -0
- package/lib/components/Switch/Switch.namespace.d.ts.map +1 -0
- package/lib/components/Switch/Switch.namespace.js +11 -0
- package/lib/components/Switch/index.d.ts +3 -0
- package/lib/components/Switch/index.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.d.ts +34 -0
- package/lib/components/TagGroup/TagGroup.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.jsx +57 -0
- package/lib/components/TagGroup/TagGroup.namespace.d.ts +2 -0
- package/lib/components/TagGroup/TagGroup.namespace.d.ts.map +1 -0
- package/lib/components/TagGroup/TagGroup.namespace.js +10 -0
- package/lib/components/TagGroup/index.d.ts +3 -0
- package/lib/components/TagGroup/index.d.ts.map +1 -0
- package/lib/components/Text/Text.d.ts +7 -0
- package/lib/components/Text/Text.d.ts.map +1 -0
- package/lib/components/Text/Text.jsx +28 -0
- package/lib/components/Text/index.d.ts +2 -0
- package/lib/components/Text/index.d.ts.map +1 -0
- package/lib/components/index.d.ts +12 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/hooks/index.d.ts +5 -0
- package/lib/hooks/index.d.ts.map +1 -0
- package/lib/hooks/useControllableState.d.ts +15 -0
- package/lib/hooks/useControllableState.d.ts.map +1 -0
- package/lib/hooks/useControllableState.js +27 -0
- package/lib/hooks/useIconColor.d.ts +19 -0
- package/lib/hooks/useIconColor.d.ts.map +1 -0
- package/lib/hooks/useIconColor.js +38 -0
- package/lib/hooks/usePressTap.d.ts +27 -0
- package/lib/hooks/usePressTap.d.ts.map +1 -0
- package/lib/hooks/usePressTap.js +35 -0
- package/lib/hooks/useSafeArea.d.ts +19 -0
- package/lib/hooks/useSafeArea.d.ts.map +1 -0
- package/lib/hooks/useSafeArea.js +33 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +26 -0
- package/lib/types.d.ts +33 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/utils/children.d.ts +3 -0
- package/lib/utils/children.d.ts.map +1 -0
- package/lib/utils/children.js +8 -0
- package/lib/utils/create-slot-recipe-context.d.ts +27 -0
- package/lib/utils/create-slot-recipe-context.d.ts.map +1 -0
- package/lib/utils/create-slot-recipe-context.jsx +94 -0
- package/lib/utils/get-seed-class-name.d.ts +22 -0
- package/lib/utils/get-seed-class-name.d.ts.map +1 -0
- package/lib/utils/get-seed-class-name.js +28 -0
- package/lib/utils/index.d.ts +5 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/resolve-recipe-token.d.ts +38 -0
- package/lib/utils/resolve-recipe-token.d.ts.map +1 -0
- package/lib/utils/resolve-recipe-token.js +49 -0
- package/lib/utils/split-multiple-variants-props.d.ts +29 -0
- package/lib/utils/split-multiple-variants-props.d.ts.map +1 -0
- package/lib/utils/split-multiple-variants-props.js +34 -0
- package/lib/utils/styled.d.ts +83 -0
- package/lib/utils/styled.d.ts.map +1 -0
- package/lib/utils/styled.js +144 -0
- package/package.json +54 -0
- package/src/components/ActionButton/ActionButton.test.tsx +137 -0
- package/src/components/ActionButton/ActionButton.tsx +340 -0
- package/src/components/ActionButton/index.ts +1 -0
- package/src/components/BottomSheet/BottomSheet.namespace.ts +24 -0
- package/src/components/BottomSheet/BottomSheet.test.tsx +153 -0
- package/src/components/BottomSheet/BottomSheet.tsx +397 -0
- package/src/components/BottomSheet/index.ts +27 -0
- package/src/components/Box/Box.test.tsx +85 -0
- package/src/components/Box/Box.tsx +39 -0
- package/src/components/Box/index.ts +1 -0
- package/src/components/Checkbox/Checkbox.namespace.ts +12 -0
- package/src/components/Checkbox/Checkbox.tsx +282 -0
- package/src/components/Checkbox/index.ts +14 -0
- package/src/components/Icon/Icon.tsx +265 -0
- package/src/components/Icon/index.ts +8 -0
- package/src/components/ProgressCircle/ProgressCircle.namespace.ts +5 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +424 -0
- package/src/components/ProgressCircle/index.ts +9 -0
- package/src/components/RadioGroup/RadioGroup.namespace.ts +12 -0
- package/src/components/RadioGroup/RadioGroup.tsx +320 -0
- package/src/components/RadioGroup/index.ts +14 -0
- package/src/components/Stack/Stack.tsx +97 -0
- package/src/components/Stack/index.ts +1 -0
- package/src/components/Switch/Switch.namespace.ts +10 -0
- package/src/components/Switch/Switch.tsx +200 -0
- package/src/components/Switch/index.ts +12 -0
- package/src/components/TagGroup/TagGroup.namespace.ts +8 -0
- package/src/components/TagGroup/TagGroup.tsx +127 -0
- package/src/components/TagGroup/index.ts +10 -0
- package/src/components/Text/Text.tsx +64 -0
- package/src/components/Text/index.ts +1 -0
- package/src/components/index.ts +11 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useControllableState.test.ts +120 -0
- package/src/hooks/useControllableState.ts +38 -0
- package/src/hooks/useIconColor.test.ts +13 -0
- package/src/hooks/useIconColor.ts +67 -0
- package/src/hooks/usePressTap.test.ts +129 -0
- package/src/hooks/usePressTap.ts +58 -0
- package/src/hooks/useSafeArea.test.ts +83 -0
- package/src/hooks/useSafeArea.ts +56 -0
- package/src/index.ts +4 -0
- package/src/types.ts +45 -0
- package/src/utils/children.ts +13 -0
- package/src/utils/create-slot-recipe-context.test.tsx +96 -0
- package/src/utils/create-slot-recipe-context.tsx +187 -0
- package/src/utils/get-seed-class-name.ts +47 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/resolve-recipe-token.ts +47 -0
- package/src/utils/split-multiple-variants-props.test.ts +61 -0
- package/src/utils/split-multiple-variants-props.ts +59 -0
- package/src/utils/styled.ts +442 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { handleColor, handleFontSize, handleFontWeight, handleLineHeight } from "../../utils/styled.js";
|
|
2
|
+
import { typography } from "@seed-design/lynx-css/vars/component";
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import * as React from "@lynx-js/react";
|
|
5
|
+
//#region src/components/Text/Text.tsx
|
|
6
|
+
function capitalize(value) {
|
|
7
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
8
|
+
}
|
|
9
|
+
function getTypographyStyle(textStyle) {
|
|
10
|
+
return typography[`textStyle${capitalize(textStyle ?? "t5Regular")}`].enabled.root;
|
|
11
|
+
}
|
|
12
|
+
var Text = React.forwardRef((props, ref) => {
|
|
13
|
+
const { color, textStyle, fontSize, lineHeight, fontWeight, align, children, className, style, ...nativeProps } = props;
|
|
14
|
+
const typographyStyle = getTypographyStyle(textStyle);
|
|
15
|
+
return <text {...ref ? { ref } : {}} {...nativeProps} className={clsx(className)} style={{
|
|
16
|
+
color: handleColor(color),
|
|
17
|
+
fontSize: handleFontSize(fontSize) ?? typographyStyle.fontSize,
|
|
18
|
+
lineHeight: handleLineHeight(lineHeight ?? fontSize) ?? typographyStyle.lineHeight,
|
|
19
|
+
fontWeight: handleFontWeight(fontWeight) ?? typographyStyle.fontWeight,
|
|
20
|
+
textAlign: align,
|
|
21
|
+
...style
|
|
22
|
+
}}>
|
|
23
|
+
{children}
|
|
24
|
+
</text>;
|
|
25
|
+
});
|
|
26
|
+
Text.displayName = "Text";
|
|
27
|
+
//#endregion
|
|
28
|
+
export { Text };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Text/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from './ActionButton';
|
|
2
|
+
export * from './Box';
|
|
3
|
+
export * from './BottomSheet';
|
|
4
|
+
export * from './Checkbox';
|
|
5
|
+
export * from './Icon';
|
|
6
|
+
export * from './ProgressCircle';
|
|
7
|
+
export * from './RadioGroup';
|
|
8
|
+
export * from './Stack';
|
|
9
|
+
export * from './Switch';
|
|
10
|
+
export * from './TagGroup';
|
|
11
|
+
export * from './Text';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface UseControllableStateProps<T> {
|
|
2
|
+
value?: T;
|
|
3
|
+
defaultValue: T;
|
|
4
|
+
onChange?: (value: T) => void;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Controlled/uncontrolled state pattern for Lynx components.
|
|
8
|
+
*
|
|
9
|
+
* - When `value` is provided, the component is controlled.
|
|
10
|
+
* - When `value` is `undefined`, the component manages its own state
|
|
11
|
+
* starting from `defaultValue`.
|
|
12
|
+
* - `onChange` fires in both modes.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useControllableState<T>(props: UseControllableStateProps<T>): [T, (value: T) => void];
|
|
15
|
+
//# sourceMappingURL=useControllableState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useControllableState.d.ts","sourceRoot":"","sources":["../../src/hooks/useControllableState.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,KAAK,CAAC,EAAE,CAAC,CAAC;IACV,YAAY,EAAE,CAAC,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,KAAK,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAClC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,CAkBzB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useRef, useState } from "@lynx-js/react";
|
|
2
|
+
import { useMemoizedFn } from "@lynx-js/lynx-ui-common";
|
|
3
|
+
//#region src/hooks/useControllableState.ts
|
|
4
|
+
/**
|
|
5
|
+
* Controlled/uncontrolled state pattern for Lynx components.
|
|
6
|
+
*
|
|
7
|
+
* - When `value` is provided, the component is controlled.
|
|
8
|
+
* - When `value` is `undefined`, the component manages its own state
|
|
9
|
+
* starting from `defaultValue`.
|
|
10
|
+
* - `onChange` fires in both modes.
|
|
11
|
+
*/
|
|
12
|
+
function useControllableState(props) {
|
|
13
|
+
const { value, defaultValue, onChange } = props;
|
|
14
|
+
const isControlled = value !== void 0;
|
|
15
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
|
|
16
|
+
const currentValue = isControlled ? value : uncontrolledValue;
|
|
17
|
+
const prevValueRef = useRef(currentValue);
|
|
18
|
+
return [currentValue, useMemoizedFn((nextValue) => {
|
|
19
|
+
if (!isControlled) setUncontrolledValue(nextValue);
|
|
20
|
+
if (nextValue !== prevValueRef.current) {
|
|
21
|
+
onChange?.(nextValue);
|
|
22
|
+
prevValueRef.current = nextValue;
|
|
23
|
+
}
|
|
24
|
+
})];
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { useControllableState };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { MainThread } from '@lynx-js/types';
|
|
2
|
+
import { DependencyList, RefObject } from '@lynx-js/react';
|
|
3
|
+
export interface UseIconColorOptions {
|
|
4
|
+
sourceRef?: RefObject<MainThread.Element>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Lynx `<image>` 의 tint color 를 recipe 의 CSS `color` 로부터 main-thread 에서 읽어
|
|
8
|
+
* `tint-color` attribute 로 mirror. `deps` 가 바뀌면 재동기화.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const iconColorProps = useIconColor([variant, disabled, loading]);
|
|
12
|
+
* return cloneElement(iconChild, iconColorProps);
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function useIconColor(deps: DependencyList, options?: UseIconColorOptions): {
|
|
16
|
+
ref: RefObject<MainThread.Element>;
|
|
17
|
+
"main-thread:binduiappear": () => void;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=useIconColor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIconColor.d.ts","sourceRoot":"","sources":["../../src/hooks/useIconColor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAOhE,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;CAC3C;AAyBD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,cAAc,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAC5B;IACD,GAAG,EAAE,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACnC,0BAA0B,EAAE,MAAM,IAAI,CAAC;CACxC,CAeA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { runOnMainThread, useEffect, useMainThreadRef } from "@lynx-js/react";
|
|
2
|
+
//#region src/hooks/useIconColor.ts
|
|
3
|
+
function syncTintColor(targetRef, sourceRef) {
|
|
4
|
+
"main thread";
|
|
5
|
+
const target = targetRef.current;
|
|
6
|
+
if (!target) return;
|
|
7
|
+
const source = sourceRef?.current ?? target;
|
|
8
|
+
let color;
|
|
9
|
+
if (typeof source.getComputedStyleProperty === "function") color = source.getComputedStyleProperty("color");
|
|
10
|
+
else if (typeof source.getComputedCssProperty === "function") color = source.getComputedCssProperty("color");
|
|
11
|
+
if (color) target.setAttribute("tint-color", color);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Lynx `<image>` 의 tint color 를 recipe 의 CSS `color` 로부터 main-thread 에서 읽어
|
|
15
|
+
* `tint-color` attribute 로 mirror. `deps` 가 바뀌면 재동기화.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const iconColorProps = useIconColor([variant, disabled, loading]);
|
|
19
|
+
* return cloneElement(iconChild, iconColorProps);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
function useIconColor(deps, options) {
|
|
23
|
+
const ref = useMainThreadRef(null);
|
|
24
|
+
const sourceRef = options?.sourceRef;
|
|
25
|
+
function syncOnUiAppear() {
|
|
26
|
+
"main thread";
|
|
27
|
+
syncTintColor(ref, sourceRef);
|
|
28
|
+
}
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
runOnMainThread(syncTintColor)(ref, sourceRef);
|
|
31
|
+
}, deps);
|
|
32
|
+
return {
|
|
33
|
+
ref,
|
|
34
|
+
"main-thread:binduiappear": syncOnUiAppear
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//#endregion
|
|
38
|
+
export { useIconColor };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseTouchEvent, EventHandler, Target } from '@lynx-js/types';
|
|
2
|
+
import { LynxTouchProps } from '../types';
|
|
3
|
+
type TouchHandler = EventHandler<BaseTouchEvent<Target>>;
|
|
4
|
+
export interface UsePressTapOptions {
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
onTap?: TouchHandler;
|
|
7
|
+
mainThreadOnTap?: LynxTouchProps["main-thread:bindtap"];
|
|
8
|
+
}
|
|
9
|
+
export interface UsePressTapReturn {
|
|
10
|
+
pressed: boolean;
|
|
11
|
+
bindtap: TouchHandler;
|
|
12
|
+
bindtouchstart: TouchHandler;
|
|
13
|
+
bindtouchend: TouchHandler;
|
|
14
|
+
bindtouchcancel: TouchHandler;
|
|
15
|
+
"main-thread:bindtap"?: LynxTouchProps["main-thread:bindtap"];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Hook that provides press/tap interaction state for Lynx elements.
|
|
19
|
+
*
|
|
20
|
+
* - Tracks `pressed` state via touch events.
|
|
21
|
+
* - When `disabled` is true, the element cannot become active and no tap fires.
|
|
22
|
+
* - If the element becomes disabled during a press, the active state is cleared.
|
|
23
|
+
* - `main-thread:bindtap` is conditionally included (only when enabled and provided).
|
|
24
|
+
*/
|
|
25
|
+
export declare function usePressTap(options?: UsePressTapOptions): UsePressTapReturn;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=usePressTap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePressTap.d.ts","sourceRoot":"","sources":["../../src/hooks/usePressTap.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,KAAK,YAAY,GAAG,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAEzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,eAAe,CAAC,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,YAAY,CAAC;IACtB,cAAc,EAAE,YAAY,CAAC;IAC7B,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,YAAY,CAAC;IAC9B,qBAAqB,CAAC,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;CAC/D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CA0B/E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useState } from "@lynx-js/react";
|
|
2
|
+
import { useMemoizedFn } from "@lynx-js/lynx-ui-common";
|
|
3
|
+
//#region src/hooks/usePressTap.ts
|
|
4
|
+
/**
|
|
5
|
+
* Hook that provides press/tap interaction state for Lynx elements.
|
|
6
|
+
*
|
|
7
|
+
* - Tracks `pressed` state via touch events.
|
|
8
|
+
* - When `disabled` is true, the element cannot become active and no tap fires.
|
|
9
|
+
* - If the element becomes disabled during a press, the active state is cleared.
|
|
10
|
+
* - `main-thread:bindtap` is conditionally included (only when enabled and provided).
|
|
11
|
+
*/
|
|
12
|
+
function usePressTap(options = {}) {
|
|
13
|
+
const { disabled = false, onTap, mainThreadOnTap } = options;
|
|
14
|
+
const [pressed, setPressed] = useState(false);
|
|
15
|
+
const press = useMemoizedFn(() => {
|
|
16
|
+
if (disabled) return;
|
|
17
|
+
setPressed(true);
|
|
18
|
+
});
|
|
19
|
+
const reset = useMemoizedFn(() => {
|
|
20
|
+
setPressed(false);
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
pressed,
|
|
24
|
+
bindtap: useMemoizedFn((...args) => {
|
|
25
|
+
if (disabled) return;
|
|
26
|
+
onTap?.(...args);
|
|
27
|
+
}),
|
|
28
|
+
bindtouchstart: press,
|
|
29
|
+
bindtouchend: reset,
|
|
30
|
+
bindtouchcancel: reset,
|
|
31
|
+
...!disabled && mainThreadOnTap ? { "main-thread:bindtap": mainThreadOnTap } : {}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { usePressTap };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module "@lynx-js/types" {
|
|
2
|
+
interface GlobalProps {
|
|
3
|
+
safeAreaInsetTop?: number;
|
|
4
|
+
safeAreaInsetBottom?: number;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export interface UseSafeAreaReturn {
|
|
8
|
+
safeAreaInsetTop: string;
|
|
9
|
+
safeAreaInsetBottom: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Lynx 앱에서 top/bottom safe area inset 값을 반환합니다.
|
|
13
|
+
*
|
|
14
|
+
* `lynx.__globalProps.safeAreaInsetTop`과 `safeAreaInsetBottom`을 우선 사용하고,
|
|
15
|
+
* host가 값을 제공하지 않으면 Lynx CSS `env(safe-area-inset-*)` 값을 fallback으로
|
|
16
|
+
* 반환합니다.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useSafeArea(): UseSafeAreaReturn;
|
|
19
|
+
//# sourceMappingURL=useSafeArea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSafeArea.d.ts","sourceRoot":"","sources":["../../src/hooks/useSafeArea.ts"],"names":[],"mappings":"AAIA,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,WAAW;QACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;KAC9B;CACF;AAuBD,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CAW/C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useMemo } from "@lynx-js/react";
|
|
2
|
+
//#region src/hooks/useSafeArea.ts
|
|
3
|
+
var safeAreaProp = {
|
|
4
|
+
top: "safeAreaInsetTop",
|
|
5
|
+
bottom: "safeAreaInsetBottom"
|
|
6
|
+
};
|
|
7
|
+
function getSafeAreaEnvInset(edge) {
|
|
8
|
+
return `env(safe-area-inset-${edge})`;
|
|
9
|
+
}
|
|
10
|
+
function normalizeSafeAreaValue(value) {
|
|
11
|
+
if (typeof value !== "number" || value <= 0 || !Number.isFinite(value)) return;
|
|
12
|
+
return `${value}px`;
|
|
13
|
+
}
|
|
14
|
+
function resolveSafeAreaInset(edge, value) {
|
|
15
|
+
return normalizeSafeAreaValue(value) ?? getSafeAreaEnvInset(edge);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Lynx 앱에서 top/bottom safe area inset 값을 반환합니다.
|
|
19
|
+
*
|
|
20
|
+
* `lynx.__globalProps.safeAreaInsetTop`과 `safeAreaInsetBottom`을 우선 사용하고,
|
|
21
|
+
* host가 값을 제공하지 않으면 Lynx CSS `env(safe-area-inset-*)` 값을 fallback으로
|
|
22
|
+
* 반환합니다.
|
|
23
|
+
*/
|
|
24
|
+
function useSafeArea() {
|
|
25
|
+
const safeAreaInsetTop = lynx.__globalProps?.[safeAreaProp.top];
|
|
26
|
+
const safeAreaInsetBottom = lynx.__globalProps?.[safeAreaProp.bottom];
|
|
27
|
+
return useMemo(() => ({
|
|
28
|
+
safeAreaInsetTop: resolveSafeAreaInset("top", safeAreaInsetTop),
|
|
29
|
+
safeAreaInsetBottom: resolveSafeAreaInset("bottom", safeAreaInsetBottom)
|
|
30
|
+
}), [safeAreaInsetTop, safeAreaInsetBottom]);
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
export { useSafeArea };
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,mBAAmB,SAAS,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { usePressTap } from "./hooks/usePressTap.js";
|
|
2
|
+
import { createSlotRecipeContext } from "./utils/create-slot-recipe-context.jsx";
|
|
3
|
+
import { capitalize, resolveRecipeToken } from "./utils/resolve-recipe-token.js";
|
|
4
|
+
import { useSafeArea } from "./hooks/useSafeArea.js";
|
|
5
|
+
import { ProgressCircleRange, ProgressCircleRoot } from "./components/ProgressCircle/ProgressCircle.jsx";
|
|
6
|
+
import { ProgressCircle_namespace_exports } from "./components/ProgressCircle/ProgressCircle.namespace.js";
|
|
7
|
+
import { useIconColor } from "./hooks/useIconColor.js";
|
|
8
|
+
import { Icon, PrefixIcon, SuffixIcon } from "./components/Icon/Icon.jsx";
|
|
9
|
+
import { ActionButton } from "./components/ActionButton/ActionButton.jsx";
|
|
10
|
+
import { Box } from "./components/Box/Box.jsx";
|
|
11
|
+
import { BottomSheetBackdrop, BottomSheetBody, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHandle, BottomSheetHeader, BottomSheetPositioner, BottomSheetRoot, BottomSheetTitle, BottomSheetTrigger } from "./components/BottomSheet/BottomSheet.jsx";
|
|
12
|
+
import { BottomSheet_namespace_exports } from "./components/BottomSheet/BottomSheet.namespace.js";
|
|
13
|
+
import { useControllableState } from "./hooks/useControllableState.js";
|
|
14
|
+
import { splitMultipleVariantsProps } from "./utils/split-multiple-variants-props.js";
|
|
15
|
+
import { CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot } from "./components/Checkbox/Checkbox.jsx";
|
|
16
|
+
import { Checkbox_namespace_exports } from "./components/Checkbox/Checkbox.namespace.js";
|
|
17
|
+
import { RadioGroupItem, RadioGroupItemControl, RadioGroupItemIndicator, RadioGroupItemLabel, RadioGroupRoot } from "./components/RadioGroup/RadioGroup.jsx";
|
|
18
|
+
import { RadioGroup_namespace_exports } from "./components/RadioGroup/RadioGroup.namespace.js";
|
|
19
|
+
import { HStack, VStack } from "./components/Stack/Stack.jsx";
|
|
20
|
+
import { SwitchControl, SwitchLabel, SwitchRoot, SwitchThumb } from "./components/Switch/Switch.jsx";
|
|
21
|
+
import { Switch_namespace_exports } from "./components/Switch/Switch.namespace.js";
|
|
22
|
+
import { TagGroupItem, TagGroupItemLabel, TagGroupRoot } from "./components/TagGroup/TagGroup.jsx";
|
|
23
|
+
import { TagGroup_namespace_exports } from "./components/TagGroup/TagGroup.namespace.js";
|
|
24
|
+
import { Text } from "./components/Text/Text.jsx";
|
|
25
|
+
import { getSeedClassName } from "./utils/get-seed-class-name.js";
|
|
26
|
+
export { ActionButton, BottomSheet_namespace_exports as BottomSheet, BottomSheetBackdrop, BottomSheetBody, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHandle, BottomSheetHeader, BottomSheetPositioner, BottomSheetRoot, BottomSheetTitle, BottomSheetTrigger, Box, Checkbox_namespace_exports as Checkbox, CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot, HStack, Icon, PrefixIcon, ProgressCircle_namespace_exports as ProgressCircle, ProgressCircleRange, ProgressCircleRoot, RadioGroup_namespace_exports as RadioGroup, RadioGroupItem, RadioGroupItemControl, RadioGroupItemIndicator, RadioGroupItemLabel, RadioGroupRoot, SuffixIcon, Switch_namespace_exports as Switch, SwitchControl, SwitchLabel, SwitchRoot, SwitchThumb, TagGroup_namespace_exports as TagGroup, TagGroupItem, TagGroupItemLabel, TagGroupRoot, Text, VStack, capitalize, createSlotRecipeContext, getSeedClassName, resolveRecipeToken, splitMultipleVariantsProps, useControllableState, useIconColor, usePressTap, useSafeArea };
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ReactNode, Ref } from '@lynx-js/react';
|
|
2
|
+
import { CSSProperties, IntrinsicElements, MainThread, NodesRef, TextProps, ViewProps } from '@lynx-js/types';
|
|
3
|
+
export type LynxViewProps = IntrinsicElements["view"] & ViewProps;
|
|
4
|
+
export type LynxTextProps = IntrinsicElements["text"] & TextProps;
|
|
5
|
+
export type LynxViewRef = Ref<NodesRef>;
|
|
6
|
+
export type LynxTextRef = Ref<NodesRef>;
|
|
7
|
+
export type LynxMainThreadRef = Ref<MainThread.Element>;
|
|
8
|
+
export type LynxStyle = CSSProperties;
|
|
9
|
+
export interface LynxElementProps {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
className?: LynxViewProps["className"];
|
|
12
|
+
}
|
|
13
|
+
export interface LynxStyledElementProps extends LynxElementProps {
|
|
14
|
+
style?: LynxStyle;
|
|
15
|
+
}
|
|
16
|
+
export interface LynxPressableProps {
|
|
17
|
+
bindtap?: LynxViewProps["bindtap"];
|
|
18
|
+
"main-thread:bindtap"?: LynxViewProps["main-thread:bindtap"];
|
|
19
|
+
}
|
|
20
|
+
export interface LynxTouchProps {
|
|
21
|
+
bindtap?: LynxViewProps["bindtap"];
|
|
22
|
+
bindtouchstart?: LynxViewProps["bindtouchstart"];
|
|
23
|
+
bindtouchend?: LynxViewProps["bindtouchend"];
|
|
24
|
+
bindtouchcancel?: LynxViewProps["bindtouchcancel"];
|
|
25
|
+
"main-thread:bindtap"?: LynxViewProps["main-thread:bindtap"];
|
|
26
|
+
}
|
|
27
|
+
export interface LynxIconElementProps {
|
|
28
|
+
className?: IntrinsicElements["image"]["className"];
|
|
29
|
+
style?: LynxStyle;
|
|
30
|
+
ref?: LynxMainThreadRef;
|
|
31
|
+
"main-thread:binduiappear"?: IntrinsicElements["image"]["main-thread:binduiappear"];
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EACV,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,QAAQ,EACR,SAAS,EACT,SAAS,EACV,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AACxD,MAAM,MAAM,SAAS,GAAG,aAAa,CAAC;AAEtC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,qBAAqB,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnC,cAAc,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACjD,YAAY,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACnD,qBAAqB,CAAC,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,iBAAiB,CAAC;IACxB,0BAA0B,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,0BAA0B,CAAC,CAAC;CACrF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"children.d.ts","sourceRoot":"","sources":["../../src/utils/children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,wBAAgB,OAAO,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,EAAE,CAUxD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ElementType, ForwardRefExoticComponent, PropsWithoutRef, ReactElement, ReactNode, RefAttributes } from '@lynx-js/react';
|
|
2
|
+
type SlotRecipe<Props extends Record<string, string | boolean | undefined>, Classnames extends Record<string, string>> = ((props?: Props) => Classnames) & {
|
|
3
|
+
splitVariantProps: <T extends Props>(props: T) => [Props, Omit<T, keyof Props>];
|
|
4
|
+
};
|
|
5
|
+
export declare function createSlotRecipeContext<Props extends Record<string, string | boolean | undefined>, Classnames extends Record<string, string>>(recipe: SlotRecipe<Props, Classnames>): {
|
|
6
|
+
ClassNamesProvider: (props: {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
value: Classnames;
|
|
9
|
+
}) => ReactElement;
|
|
10
|
+
PropsProvider: (props: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
value: Props;
|
|
13
|
+
}) => ReactElement;
|
|
14
|
+
useClassNames: () => Classnames;
|
|
15
|
+
useProps: () => Props | null;
|
|
16
|
+
withRootProvider: <P>(Component: ElementType<any>, options?: {
|
|
17
|
+
defaultProps?: Partial<P>;
|
|
18
|
+
}) => ForwardRefExoticComponent<PropsWithoutRef<P>>;
|
|
19
|
+
withProvider: <T, P>(Component: ElementType<any>, slot: keyof Classnames, options?: {
|
|
20
|
+
defaultProps?: Partial<P>;
|
|
21
|
+
}) => ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
|
|
22
|
+
withContext: <T, P>(Component: ElementType<any>, slot?: keyof Classnames, options?: {
|
|
23
|
+
defaultProps?: Partial<P>;
|
|
24
|
+
}) => ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=create-slot-recipe-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-slot-recipe-context.d.ts","sourceRoot":"","sources":["../../src/utils/create-slot-recipe-context.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,yBAAyB,EACzB,eAAe,EACf,YAAY,EACZ,SAAS,EACT,aAAa,EACd,MAAM,gBAAgB,CAAC;AAGxB,KAAK,UAAU,CACb,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,EAC1D,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IACvC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,UAAU,CAAC,GAAG;IACpC,iBAAiB,EAAE,CAAC,CAAC,SAAS,KAAK,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC;CACjF,CAAC;AAUF,wBAAgB,uBAAuB,CACrC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,EAC1D,UAAU,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAEzC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,GACpC;IACD,kBAAkB,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,UAAU,CAAA;KAAE,KAAK,YAAY,CAAC;IACxF,aAAa,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,KAAK,YAAY,CAAC;IAC9E,aAAa,EAAE,MAAM,UAAU,CAAC;IAChC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,CAAC;IAC7B,gBAAgB,EAAE,CAAC,CAAC,EAClB,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,EAC3B,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;KAC3B,KACE,yBAAyB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EACjB,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,EAC3B,IAAI,EAAE,MAAM,UAAU,EACtB,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;KAC3B,KACE,yBAAyB,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAChB,SAAS,EAAE,WAAW,CAAC,GAAG,CAAC,EAC3B,IAAI,CAAC,EAAE,MAAM,UAAU,EACvB,OAAO,CAAC,EAAE;QACR,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;KAC3B,KACE,yBAAyB,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;CACvE,CAkIA"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import { createContext, forwardRef, useContext } from "@lynx-js/react";
|
|
3
|
+
//#region src/utils/create-slot-recipe-context.tsx
|
|
4
|
+
function assertNotIntrinsicComponent(Component, caller) {
|
|
5
|
+
if (typeof Component !== "string") return;
|
|
6
|
+
throw new Error(`${caller} cannot wrap intrinsic tag "${Component}" in Lynx. Native <view>/<text> slots must be rendered as literal JSX in the component file; passing intrinsic strings through createSlotRecipeContext can cause BackgroundSnapshot not found errors.`);
|
|
7
|
+
}
|
|
8
|
+
function createSlotRecipeContext(recipe) {
|
|
9
|
+
const ClassNamesContext = createContext(null);
|
|
10
|
+
const PropsContext = createContext(null);
|
|
11
|
+
const ClassNamesProvider = ({ children, value }) => {
|
|
12
|
+
return <ClassNamesContext.Provider value={value}>{children}</ClassNamesContext.Provider>;
|
|
13
|
+
};
|
|
14
|
+
const PropsProvider = ({ children, value }) => {
|
|
15
|
+
return <PropsContext.Provider value={value}>{children}</PropsContext.Provider>;
|
|
16
|
+
};
|
|
17
|
+
function useClassNames() {
|
|
18
|
+
const context = useContext(ClassNamesContext);
|
|
19
|
+
if (context === null) throw new Error("useClassNames must be used within a ClassNamesProvider. Did you forget to wrap your component in a ClassNamesProvider?");
|
|
20
|
+
return context;
|
|
21
|
+
}
|
|
22
|
+
function useProps() {
|
|
23
|
+
return useContext(PropsContext);
|
|
24
|
+
}
|
|
25
|
+
const withRootProvider = (Component, options) => {
|
|
26
|
+
assertNotIntrinsicComponent(Component, "withRootProvider");
|
|
27
|
+
const { defaultProps } = options ?? {};
|
|
28
|
+
const StyledComponent = (innerProps) => {
|
|
29
|
+
const props = {
|
|
30
|
+
...defaultProps ?? {},
|
|
31
|
+
...useProps(),
|
|
32
|
+
...innerProps
|
|
33
|
+
};
|
|
34
|
+
const [variantProps, otherProps] = recipe.splitVariantProps(props);
|
|
35
|
+
const classNames = recipe(variantProps);
|
|
36
|
+
return <ClassNamesProvider value={classNames}>
|
|
37
|
+
<PropsProvider value={variantProps}>
|
|
38
|
+
<Component {...otherProps} />
|
|
39
|
+
</PropsProvider>
|
|
40
|
+
</ClassNamesProvider>;
|
|
41
|
+
};
|
|
42
|
+
StyledComponent.displayName = Component.displayName || Component.name;
|
|
43
|
+
return StyledComponent;
|
|
44
|
+
};
|
|
45
|
+
const withProvider = (Component, slot, options) => {
|
|
46
|
+
assertNotIntrinsicComponent(Component, "withProvider");
|
|
47
|
+
const { defaultProps } = options ?? {};
|
|
48
|
+
const StyledComponent = forwardRef((innerProps, ref) => {
|
|
49
|
+
const props = {
|
|
50
|
+
...defaultProps ?? {},
|
|
51
|
+
...useProps(),
|
|
52
|
+
...innerProps
|
|
53
|
+
};
|
|
54
|
+
const [variantProps, otherProps] = recipe.splitVariantProps(props);
|
|
55
|
+
const classNames = recipe(variantProps);
|
|
56
|
+
const slotClassName = classNames[slot];
|
|
57
|
+
const userClassName = props["className"];
|
|
58
|
+
return <ClassNamesProvider value={classNames}>
|
|
59
|
+
<PropsProvider value={variantProps}>
|
|
60
|
+
<Component {...ref ? { ref } : {}} {...otherProps} className={clsx(slotClassName, userClassName)} />
|
|
61
|
+
</PropsProvider>
|
|
62
|
+
</ClassNamesProvider>;
|
|
63
|
+
});
|
|
64
|
+
StyledComponent.displayName = Component.displayName || Component.name;
|
|
65
|
+
return StyledComponent;
|
|
66
|
+
};
|
|
67
|
+
const withContext = (Component, slot, options) => {
|
|
68
|
+
assertNotIntrinsicComponent(Component, "withContext");
|
|
69
|
+
const { defaultProps } = options ?? {};
|
|
70
|
+
const StyledComponent = forwardRef((innerProps, ref) => {
|
|
71
|
+
const props = {
|
|
72
|
+
...defaultProps ?? {},
|
|
73
|
+
...innerProps
|
|
74
|
+
};
|
|
75
|
+
const classNames = useClassNames();
|
|
76
|
+
const slotClassName = slot ? classNames[slot] : void 0;
|
|
77
|
+
const userClassName = props["className"];
|
|
78
|
+
return <Component {...ref ? { ref } : {}} {...props} className={clsx(slotClassName, userClassName)} />;
|
|
79
|
+
});
|
|
80
|
+
StyledComponent.displayName = Component.displayName || Component.name;
|
|
81
|
+
return StyledComponent;
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
ClassNamesProvider,
|
|
85
|
+
PropsProvider,
|
|
86
|
+
useClassNames,
|
|
87
|
+
useProps,
|
|
88
|
+
withRootProvider,
|
|
89
|
+
withProvider,
|
|
90
|
+
withContext
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { createSlotRecipeContext };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ColorMode = "system" | "light-only" | "dark-only";
|
|
2
|
+
export interface GetSeedClassNameOptions {
|
|
3
|
+
colorMode?: ColorMode;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Lynx 앱의 root `<page>` 요소에 적용할 SEED Design className을 반환한다.
|
|
7
|
+
*
|
|
8
|
+
* 테마(dark/light)를 자동 감지하여 렌더링 전에 올바른 CSS 변수가 적용되도록 한다.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { getSeedClassName } from "@seed-design/lynx-react";
|
|
13
|
+
*
|
|
14
|
+
* root.render(
|
|
15
|
+
* <page className={getSeedClassName({ colorMode: "system" })}>
|
|
16
|
+
* <App />
|
|
17
|
+
* </page>
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function getSeedClassName(options?: GetSeedClassNameOptions): string;
|
|
22
|
+
//# sourceMappingURL=get-seed-class-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-seed-class-name.d.ts","sourceRoot":"","sources":["../../src/utils/get-seed-class-name.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAE9D,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAkB1E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/utils/get-seed-class-name.ts
|
|
2
|
+
/**
|
|
3
|
+
* Lynx 앱의 root `<page>` 요소에 적용할 SEED Design className을 반환한다.
|
|
4
|
+
*
|
|
5
|
+
* 테마(dark/light)를 자동 감지하여 렌더링 전에 올바른 CSS 변수가 적용되도록 한다.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { getSeedClassName } from "@seed-design/lynx-react";
|
|
10
|
+
*
|
|
11
|
+
* root.render(
|
|
12
|
+
* <page className={getSeedClassName({ colorMode: "system" })}>
|
|
13
|
+
* <App />
|
|
14
|
+
* </page>
|
|
15
|
+
* );
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function getSeedClassName(options) {
|
|
19
|
+
const { colorMode = "system" } = options ?? {};
|
|
20
|
+
const systemTheme = lynx?.__globalProps?.["theme"];
|
|
21
|
+
let themeClass;
|
|
22
|
+
if (colorMode === "light-only") themeClass = "seed-user-color-scheme-light";
|
|
23
|
+
else if (colorMode === "dark-only") themeClass = "seed-user-color-scheme-dark";
|
|
24
|
+
else themeClass = systemTheme?.toLowerCase() === "dark" ? "seed-user-color-scheme-dark" : "seed-user-color-scheme-light";
|
|
25
|
+
return themeClass;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { getSeedClassName };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rootage vars 객체에서 `path` 를 따라 token 값(주로 `"var(--seed-...)"` 스트링)을 꺼낸다.
|
|
3
|
+
*
|
|
4
|
+
* 쓰임새: Lynx `<image>` 의 `tint-color` / `width` / `height` 처럼 CSS 만으로는
|
|
5
|
+
* override 할 수 없거나(아이콘 패키지가 inline style 을 박는 경우 등) React 가
|
|
6
|
+
* recipe 와 같은 소스에서 꺼내 inline attribute 로 주입해야 하는 속성을 다룰 때.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { actionButton as actionButtonVars } from "@seed-design/lynx-css/vars/component";
|
|
10
|
+
* import { capitalize, resolveRecipeToken } from "@seed-design/lynx-react/utils/resolve-recipe-token";
|
|
11
|
+
*
|
|
12
|
+
* // variant × state × slot → color
|
|
13
|
+
* const color = resolveRecipeToken(actionButtonVars, [
|
|
14
|
+
* `variant${capitalize(variant)}`,
|
|
15
|
+
* state, // "enabled" | "disabled" | "loading" | "pressed"
|
|
16
|
+
* "prefixIcon",
|
|
17
|
+
* "color",
|
|
18
|
+
* ]);
|
|
19
|
+
*
|
|
20
|
+
* // size × layout → icon size
|
|
21
|
+
* const size = resolveRecipeToken(actionButtonVars, [
|
|
22
|
+
* `size${capitalize(size)}Layout${capitalize(layout)}`,
|
|
23
|
+
* "enabled",
|
|
24
|
+
* "prefixIcon",
|
|
25
|
+
* "size",
|
|
26
|
+
* ]);
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* recipe token 경로가 컴포넌트마다 조금씩 다르므로(variant/size/layout 조합 여부 등)
|
|
30
|
+
* 이 유틸은 "vars + path" 조합만 제공하고, 각 컴포넌트가 자기 path 를 만들어 호출한다.
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveRecipeToken(vars: unknown, path: readonly string[]): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* 첫 글자 대문자. recipe variant key 조립용
|
|
35
|
+
* (e.g. `variant` + `brandSolid` → `variantBrandSolid`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function capitalize<T extends string>(value: T): Capitalize<T>;
|
|
38
|
+
//# sourceMappingURL=resolve-recipe-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-recipe-token.d.ts","sourceRoot":"","sources":["../../src/utils/resolve-recipe-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAO7F;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAEpE"}
|