@musecat/uikit 0.1.1 → 0.1.2
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/.agents/references/Components/Box.md +60 -0
- package/.agents/references/Components/Button.md +49 -0
- package/.agents/references/Components/Card.md +67 -0
- package/.agents/references/Components/Checkbox.md +48 -0
- package/.agents/references/Components/CodeBox.md +31 -0
- package/.agents/references/Components/ContextMenu.md +82 -0
- package/.agents/references/Components/ContributionGraph.md +61 -0
- package/.agents/references/Components/DatePicker.md +92 -0
- package/.agents/references/Components/Divider.md +56 -0
- package/.agents/references/Components/Header.md +52 -0
- package/.agents/references/Components/Icon.md +82 -0
- package/.agents/references/Components/Input.md +60 -0
- package/.agents/references/Components/Label.md +78 -0
- package/.agents/references/Components/Layout.md +102 -0
- package/.agents/references/Components/Maps.md +63 -0
- package/.agents/references/Components/Nav.md +68 -0
- package/.agents/references/Components/Pagination.md +67 -0
- package/.agents/references/Components/Pill.md +75 -0
- package/.agents/references/Components/Profile.md +76 -0
- package/.agents/references/Components/Progress.md +72 -0
- package/.agents/references/Components/Radio.md +68 -0
- package/.agents/references/Components/Select.md +80 -0
- package/.agents/references/Components/Skeleton.md +48 -0
- package/.agents/references/Components/Spinner.md +62 -0
- package/.agents/references/Components/Text.md +73 -0
- package/.agents/references/Components/TimePicker.md +72 -0
- package/.agents/references/Components/Timeline.md +97 -0
- package/.agents/references/Components/Title.md +108 -0
- package/.agents/references/Components/Toggle.md +53 -0
- package/.agents/references/Components/Tooltip.md +62 -0
- package/.agents/references/Frameworks/DNDView.md +82 -0
- package/.agents/references/Frameworks/Dialog.md +109 -0
- package/.agents/references/Frameworks/EdgeEffect.md +64 -0
- package/.agents/references/Frameworks/HScrollView.md +76 -0
- package/.agents/references/Frameworks/ImageView.md +67 -0
- package/.agents/references/Frameworks/Motion.md +62 -0
- package/.agents/references/Frameworks/Pressable.md +79 -0
- package/.agents/references/Frameworks/Squircle.md +50 -0
- package/.agents/references/Frameworks/Theme.md +68 -0
- package/.agents/references/Frameworks/Toaster.md +67 -0
- package/.agents/references/Frameworks/View.md +81 -0
- package/.agents/references/Frameworks/_shared.md +74 -0
- package/.agents/references/Styles/Animation.md +43 -0
- package/.agents/references/Styles/Color.md +45 -0
- package/.agents/references/Styles/Font.md +37 -0
- package/.agents/references/Styles/Icon.md +43 -0
- package/.agents/references/Styles/Importer.md +19 -0
- package/.agents/references/Styles/System.md +27 -0
- package/.agents/references/Styles/Textstyle.md +45 -0
- package/.agents/references/Styles/Theme.md +51 -0
- package/.agents/references/Styles/Viewport-global.md +42 -0
- package/.agents/references/Styles/Viewport.md +42 -0
- package/README.md +4 -0
- package/package.json +2 -1
- package/packages/Styles/_icon.scss +2 -0
- package/packages/Styles/_importer.scss +0 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Tooltip
|
|
2
|
+
|
|
3
|
+
## 1. Purpose
|
|
4
|
+
|
|
5
|
+
A component that displays a popup bubble (`content`) with additional explanation or information when hovering over or focusing a specific UI element (`trigger`).
|
|
6
|
+
|
|
7
|
+
## 2. Usage Logic
|
|
8
|
+
|
|
9
|
+
- Positions the `content` popup above the React element passed as `trigger`.
|
|
10
|
+
- Built-in position auto-adjustment (clamp and flip) logic calculates and adjusts (ClampShift) the position so it is not clipped at screen edges.
|
|
11
|
+
- The `placement` prop specifies the bubble's default position and alignment direction (default: `"top"`).
|
|
12
|
+
- The `delay` prop adjusts the delay before the tooltip appears on hover.
|
|
13
|
+
- Flexible controlled and uncontrolled usage via `open`, `defaultOpen`, `onOpenChange`.
|
|
14
|
+
- Setting `interactive` to `true` keeps the bubble from disappearing immediately when the mouse moves over it, enabling interaction.
|
|
15
|
+
|
|
16
|
+
## 3. Type Signatures
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
export type TooltipPlacement =
|
|
20
|
+
"top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end";
|
|
21
|
+
|
|
22
|
+
export interface TooltipProps extends BorderProps {
|
|
23
|
+
trigger: React.ReactNode;
|
|
24
|
+
content: React.ReactNode;
|
|
25
|
+
placement?: TooltipPlacement;
|
|
26
|
+
open?: boolean;
|
|
27
|
+
defaultOpen?: boolean;
|
|
28
|
+
onOpenChange?: (open: boolean) => void;
|
|
29
|
+
delay?: number;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
interactive?: boolean;
|
|
32
|
+
flip?: boolean;
|
|
33
|
+
className?: string;
|
|
34
|
+
contentClassName?: string;
|
|
35
|
+
maxWidth?: number | string;
|
|
36
|
+
|
|
37
|
+
themePreset?: ThemePreset;
|
|
38
|
+
background?: ThemeBackgroundPaint;
|
|
39
|
+
color?: ThemePaint;
|
|
40
|
+
radius?: RadiusValue;
|
|
41
|
+
|
|
42
|
+
"data-color-mode"?: string;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 4. Example Code
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import Tooltip from "./Tooltip";
|
|
50
|
+
import Pressable from "../../Frameworks/Pressable/Pressable";
|
|
51
|
+
|
|
52
|
+
function Example() {
|
|
53
|
+
return (
|
|
54
|
+
<Tooltip
|
|
55
|
+
placement="top"
|
|
56
|
+
content="This is some additional information."
|
|
57
|
+
delay={300}
|
|
58
|
+
trigger={<Pressable>Hover me</Pressable>}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# DNDView Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`DNDView` is a component that provides list reordering (Reorder) via drag-and-drop (DnD). Internally uses `@dnd-kit/core` and `@dnd-kit/sortable`, fully supporting mouse, touch, and keyboard accessibility.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- Provide an `items` array and a `getKey` function to uniquely identify them.
|
|
10
|
+
- Define each item's appearance via the `renderItem` function; rendering the `handle` property from the `state` argument passed in makes that area the drag handle.
|
|
11
|
+
- When order changes, the `onReorder(newItems)` callback is called, so update state in the parent component.
|
|
12
|
+
- The `strategy` prop selects the sorting algorithm (`vertical`, `horizontal`, `rect`), and keyboard navigation is optimized for direction-key movement per this strategy.
|
|
13
|
+
|
|
14
|
+
## Type Signatures
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import type { UniqueIdentifier } from "@dnd-kit/core";
|
|
18
|
+
import type { ReactNode } from "react";
|
|
19
|
+
|
|
20
|
+
export type DNDViewItemState<T> = {
|
|
21
|
+
item: T;
|
|
22
|
+
id: UniqueIdentifier;
|
|
23
|
+
index: number;
|
|
24
|
+
dragging: boolean;
|
|
25
|
+
sorting: boolean;
|
|
26
|
+
handle: ReactNode;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type DNDViewStrategy = "vertical" | "horizontal" | "rect";
|
|
30
|
+
|
|
31
|
+
export interface DNDViewProps<T> extends ViewProps {
|
|
32
|
+
items: T[];
|
|
33
|
+
onReorder: (items: T[]) => void;
|
|
34
|
+
getKey: (item: T) => UniqueIdentifier;
|
|
35
|
+
renderItem: (item: T, state: DNDViewItemState<T>) => ReactNode;
|
|
36
|
+
renderHandle?: (
|
|
37
|
+
props: HTMLAttributes<HTMLElement>,
|
|
38
|
+
state: DNDViewItemState<T>,
|
|
39
|
+
) => ReactNode;
|
|
40
|
+
dragHandle?: boolean;
|
|
41
|
+
keyboard?: boolean;
|
|
42
|
+
strategy?: DNDViewStrategy;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Example Code
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import View from "@/packages/Frameworks/View";
|
|
50
|
+
import { useState } from "react";
|
|
51
|
+
|
|
52
|
+
function SortableList() {
|
|
53
|
+
const [items, setItems] = useState([
|
|
54
|
+
{ id: "1", name: "Item 1" },
|
|
55
|
+
{ id: "2", name: "Item 2" },
|
|
56
|
+
{ id: "3", name: "Item 3" },
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<View.DND
|
|
61
|
+
items={items}
|
|
62
|
+
getKey={(item) => item.id}
|
|
63
|
+
onReorder={setItems}
|
|
64
|
+
strategy="vertical"
|
|
65
|
+
gap={8}
|
|
66
|
+
renderItem={(item, { dragging, handle }) => (
|
|
67
|
+
<View
|
|
68
|
+
row
|
|
69
|
+
alignItems="center"
|
|
70
|
+
padding={16}
|
|
71
|
+
radius="R8"
|
|
72
|
+
background="Base1"
|
|
73
|
+
shadow={dragging ? "Bold" : "None"} // emphasize while dragging
|
|
74
|
+
>
|
|
75
|
+
{handle} {/* Grab and drag this part */}
|
|
76
|
+
<span style={{ marginLeft: 16 }}>{item.name}</span>
|
|
77
|
+
</View>
|
|
78
|
+
)}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Dialog Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `Dialog` framework is a universal framework that centrally manages all overlay UI such as popover, modal, sheet, and funnel. It supports both a global-state-based imperative API (`dialog(...)`) and a declarative component (`<Dialog />`).
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **Imperative**: Call `dialog.modal({ ... })` or `dialog.popover(element, { ... })` to render a dialog from anywhere. (Mounting `<DialogBootstrap />` somewhere in the app root is required)
|
|
10
|
+
- **Declarative**: Declare inside a component's JSX as `<Dialog open={isOpen} onOpenChange={setIsOpen} mode="modal" ... />`.
|
|
11
|
+
- **Per-mode characteristics**:
|
|
12
|
+
- `popover`: Positioned around a specific element (`anchorRef`).
|
|
13
|
+
- `modal`: A traditional modal positioned at the center of the screen.
|
|
14
|
+
- `sheet`: A Bottom Sheet that rises from the bottom on mobile. (Supports gestures, snap points)
|
|
15
|
+
- `mobileMode`: A useful option that is `modal` on desktop but automatically converts to `sheet` on mobile (when `isMobile` condition is met).
|
|
16
|
+
- **Common components**: Header, Footer (button arrangement automation), background (Dim), exit animation handling, keyboard Escape handling, etc.
|
|
17
|
+
|
|
18
|
+
## Type Signatures
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import type { ReactNode, RefObject } from "react";
|
|
22
|
+
import type {
|
|
23
|
+
PopoverConfig,
|
|
24
|
+
ModalConfig,
|
|
25
|
+
SheetConfig,
|
|
26
|
+
FunnelConfig,
|
|
27
|
+
ExitConfig,
|
|
28
|
+
} from "./Dialog.types";
|
|
29
|
+
import type { ThemeSystemProps, BorderProps } from "../Theme/Theme.types";
|
|
30
|
+
import type { RadiusProps } from "../Theme/Radius.types";
|
|
31
|
+
|
|
32
|
+
export type DialogMode = "popover" | "modal" | "sheet";
|
|
33
|
+
export type DialogMobileMode = "modal" | "sheet";
|
|
34
|
+
|
|
35
|
+
// Shared by all mode configs
|
|
36
|
+
type DialogBaseConfig = ThemeSystemProps & BorderProps & RadiusProps;
|
|
37
|
+
|
|
38
|
+
export interface DialogProps {
|
|
39
|
+
open?: boolean;
|
|
40
|
+
onOpenChange?: (open: boolean) => void;
|
|
41
|
+
id?: string;
|
|
42
|
+
mode: DialogMode;
|
|
43
|
+
mobileMode?: DialogMobileMode;
|
|
44
|
+
|
|
45
|
+
// Per-mode config (choose one)
|
|
46
|
+
popover?: PopoverConfig;
|
|
47
|
+
modal?: ModalConfig;
|
|
48
|
+
sheet?: SheetConfig;
|
|
49
|
+
funnel?: FunnelConfig; // multi-step funnel flow control
|
|
50
|
+
|
|
51
|
+
content?: ReactNode; // dialog body
|
|
52
|
+
exit?: ExitConfig; // outside click, cancel button behavior
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Imperative API
|
|
56
|
+
export function dialog(props: DialogProps): DialogInstance;
|
|
57
|
+
dialog.modal = (props: Omit<DialogProps, "mode">) => DialogInstance;
|
|
58
|
+
dialog.sheet = (props: Omit<DialogProps, "mode">) => DialogInstance;
|
|
59
|
+
dialog.popover = (anchor: HTMLElement, props: Omit<DialogProps, "mode">) =>
|
|
60
|
+
DialogInstance;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Example Code
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import Dialog, { dialog } from "@/packages/Frameworks/Dialog/Dialog";
|
|
67
|
+
import Pressable from "@/packages/Frameworks/Pressable";
|
|
68
|
+
import { useState } from "react";
|
|
69
|
+
|
|
70
|
+
function Example() {
|
|
71
|
+
const [open, setOpen] = useState(false);
|
|
72
|
+
|
|
73
|
+
// 1. Imperative modal call
|
|
74
|
+
const showModal = () => {
|
|
75
|
+
dialog.modal({
|
|
76
|
+
modal: {
|
|
77
|
+
header: { title: "Imperative Modal" },
|
|
78
|
+
footer: {
|
|
79
|
+
buttons: [{ text: "Confirm", onClick: (e, close) => close() }],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
content: <div>This modal can be called from anywhere.</div>,
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div>
|
|
88
|
+
<button onClick={showModal}>Open Imperative Modal</button>
|
|
89
|
+
<button onClick={() => setOpen(true)}>Open Declarative Sheet</button>
|
|
90
|
+
|
|
91
|
+
{/* 2. Declarative sheet rendering */}
|
|
92
|
+
<Dialog
|
|
93
|
+
mode="sheet"
|
|
94
|
+
open={open}
|
|
95
|
+
onOpenChange={setOpen}
|
|
96
|
+
sheet={{
|
|
97
|
+
header: { title: "Select Option" },
|
|
98
|
+
snapPoints: [300, 600],
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
<div style={{ padding: 20 }}>
|
|
102
|
+
<Pressable>Menu 1</Pressable>
|
|
103
|
+
<Pressable>Menu 2</Pressable>
|
|
104
|
+
</div>
|
|
105
|
+
</Dialog>
|
|
106
|
+
</div>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# EdgeEffect Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `EdgeEffect` framework adds a blurry gradient overlay to a specific directional edge (top, bottom, left, right) of a container, providing a visual effect where the inner content fades out smoothly at both ends of the screen.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- Rendered on top of the `View` component and mainly used to apply a gradient to the edge of a scrollable element.
|
|
10
|
+
- Specifying one of `"left"`, `"right"`, `"top"`, `"bottom"` for the `side` prop spreads the gradient toward the opposite direction of that side.
|
|
11
|
+
- `pointerEvents: "none"` is applied by default so it does not interfere with click/touch events.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { ViewProps } from "../View/View.types";
|
|
17
|
+
|
|
18
|
+
export interface EdgeEffectProps extends Omit<ViewProps, "children"> {
|
|
19
|
+
side?: "left" | "right" | "top" | "bottom";
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Example Code
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import EdgeEffect from "@/packages/Frameworks/EdgeEffect";
|
|
27
|
+
import View from "@/packages/Frameworks/View";
|
|
28
|
+
|
|
29
|
+
function ScrollContainer() {
|
|
30
|
+
return (
|
|
31
|
+
<View style={{ position: "relative", height: 300, overflow: "hidden" }}>
|
|
32
|
+
{/* Top edge fade effect */}
|
|
33
|
+
<EdgeEffect
|
|
34
|
+
side="top"
|
|
35
|
+
style={{
|
|
36
|
+
position: "absolute",
|
|
37
|
+
top: 0,
|
|
38
|
+
left: 0,
|
|
39
|
+
right: 0,
|
|
40
|
+
height: 40,
|
|
41
|
+
zIndex: 10,
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
|
|
45
|
+
<View style={{ overflowY: "auto", height: "100%" }}>
|
|
46
|
+
{/* contents... */}
|
|
47
|
+
</View>
|
|
48
|
+
|
|
49
|
+
{/* Bottom edge fade effect */}
|
|
50
|
+
<EdgeEffect
|
|
51
|
+
side="bottom"
|
|
52
|
+
style={{
|
|
53
|
+
position: "absolute",
|
|
54
|
+
bottom: 0,
|
|
55
|
+
left: 0,
|
|
56
|
+
right: 0,
|
|
57
|
+
height: 40,
|
|
58
|
+
zIndex: 10,
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
</View>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# HScrollView Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`HScrollView` is a horizontal scroll container supporting both mobile and desktop environments. Internally uses `embla-carousel-react` to provide a smooth horizontal scroll experience based on touch swipe and mouse wheel, and can automatically apply EdgeEffect at both ends.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- The `active` prop specifies whether scrolling is enabled. Passing a string-based viewport breakpoint ("w1", "w2", "w3", "w4") allows responsive activation of the swiper only below a specific breakpoint.
|
|
10
|
+
- The carousel engine (Embla) is activated only when there are multiple child elements; with one or fewer, or when inactive, it falls back to a normal Flexbox structure.
|
|
11
|
+
- The `renderControls` render prop can freely inject left/right scroll control buttons outside or inside the swiper.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { CSSProperties, ReactNode } from "react";
|
|
17
|
+
import type { ViewProps } from "../View.types";
|
|
18
|
+
|
|
19
|
+
export type HScrollViewViewport = "w1" | "w2" | "w3" | "w4";
|
|
20
|
+
export type HScrollViewActive = boolean | HScrollViewViewport;
|
|
21
|
+
|
|
22
|
+
export interface HScrollViewControls {
|
|
23
|
+
scrollPrev: () => void;
|
|
24
|
+
scrollNext: () => void;
|
|
25
|
+
canScrollPrev: boolean;
|
|
26
|
+
canScrollNext: boolean;
|
|
27
|
+
isScrollActive: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface HScrollViewProps extends Omit<
|
|
31
|
+
HTMLAttributes<HTMLDivElement>,
|
|
32
|
+
"color"
|
|
33
|
+
> {
|
|
34
|
+
active?: HScrollViewActive;
|
|
35
|
+
rootStyle?: CSSProperties;
|
|
36
|
+
containerStyle?: CSSProperties;
|
|
37
|
+
activeContainerStyle?: CSSProperties;
|
|
38
|
+
inactiveContainerStyle?: CSSProperties;
|
|
39
|
+
itemWidth?: number | string;
|
|
40
|
+
itemHeight?: number | string;
|
|
41
|
+
renderControls?: (controls: HScrollViewControls) => ReactNode;
|
|
42
|
+
showEdgeEffect?: boolean;
|
|
43
|
+
// ... ViewProps (gap, padding, margin, width, theme, etc.)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Example Code
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import HScrollView from "@/packages/Frameworks/View/HScrollView/HScrollView";
|
|
51
|
+
import View from "@/packages/Frameworks/View";
|
|
52
|
+
|
|
53
|
+
function HorizontalList() {
|
|
54
|
+
return (
|
|
55
|
+
<HScrollView
|
|
56
|
+
active="w3" // enable horizontal scroll only below 768px
|
|
57
|
+
gap={16}
|
|
58
|
+
showEdgeEffect={true}
|
|
59
|
+
itemWidth="20rem"
|
|
60
|
+
>
|
|
61
|
+
<View background="Base3" padding={24}>
|
|
62
|
+
Item 1
|
|
63
|
+
</View>
|
|
64
|
+
<View background="Base3" padding={24}>
|
|
65
|
+
Item 2
|
|
66
|
+
</View>
|
|
67
|
+
<View background="Base3" padding={24}>
|
|
68
|
+
Item 3
|
|
69
|
+
</View>
|
|
70
|
+
<View background="Base3" padding={24}>
|
|
71
|
+
Item 4
|
|
72
|
+
</View>
|
|
73
|
+
</HScrollView>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ImageView Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `ImageView` framework is a composite component that renders (single and multiple) images optimally and provides a full-screen or popup modal zoom/slide view (gallery) on click. Internally supports Next.js's `next/image`, and uses `embla-carousel` in slide mode.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- Passing a single string to `src` renders one image; passing an array (`string[]` or `ImageItem[]`) displays it as a horizontally scrolling gallery.
|
|
10
|
+
- Passing the `dialog` prop opens an immersive image viewer as a modal based on the `Dialog` framework when the image is clicked.
|
|
11
|
+
- Includes its own blur data generation utility (fallback blur) to provide a natural placeholder during loading.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
export type ImageItem = {
|
|
17
|
+
id: number;
|
|
18
|
+
src: string;
|
|
19
|
+
alt: string;
|
|
20
|
+
srcDialog?: string; // high-quality image to show in dialog mode
|
|
21
|
+
blurDataURL?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export interface ImageProps extends RadiusProps {
|
|
25
|
+
src: string | string[] | ImageItem[];
|
|
26
|
+
alt?: string | string[];
|
|
27
|
+
width?: number | string | (number | string)[];
|
|
28
|
+
height?: number | string | (number | string)[];
|
|
29
|
+
priority?: boolean;
|
|
30
|
+
groupWidth?: string;
|
|
31
|
+
groupHeight?: string;
|
|
32
|
+
groupGap?: number | string;
|
|
33
|
+
overlay?: ReactNode | ReactNode[];
|
|
34
|
+
control?: boolean | { left?: boolean; right?: boolean /* ... */ };
|
|
35
|
+
dialog?: {
|
|
36
|
+
overlay?: ReactNode | ReactNode[];
|
|
37
|
+
header?: { content?: ReactNode };
|
|
38
|
+
footer?: { list?: boolean; counter?: boolean /* ... */ };
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Example Code
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import View from "@/packages/Frameworks/View";
|
|
47
|
+
|
|
48
|
+
function PhotoGallery() {
|
|
49
|
+
const images = [
|
|
50
|
+
{ id: 1, src: "/img1.jpg", alt: "Photo 1" },
|
|
51
|
+
{ id: 2, src: "/img2.jpg", alt: "Photo 2" },
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<ImageView
|
|
56
|
+
src={images}
|
|
57
|
+
radius="R12"
|
|
58
|
+
groupWidth="240px"
|
|
59
|
+
groupHeight="160px"
|
|
60
|
+
control={{ left: true, right: true }}
|
|
61
|
+
dialog={{
|
|
62
|
+
footer: { list: true, counter: true },
|
|
63
|
+
}}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Motion Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `Motion` framework is used to provide consistent animation effects and transition presets within UIKit. It centrally manages `framer-motion` (or `motion/react`) configuration values mainly applied to motion-based interfaces such as modals, sheets, and popovers.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- `motionTransitions`: An object managing animation physical properties (stiffness, damping, mass, etc.). Defines default behaviors such as spring or tween.
|
|
10
|
+
- `motionPresets`: Provides `initial`, `animate`, `exit` state definition objects or factory functions for specific UI components like modal, popover, and backdrop.
|
|
11
|
+
|
|
12
|
+
## Type Signatures
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// Inside Motion.presets.ts
|
|
16
|
+
|
|
17
|
+
export const motionTransitions = {
|
|
18
|
+
sheet: { snap, entrance, exit },
|
|
19
|
+
modal: { transition },
|
|
20
|
+
popover: { transition },
|
|
21
|
+
backdrop: { transition },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const motionPresets = {
|
|
25
|
+
modal: { initial, animate, exit, transition },
|
|
26
|
+
popover: (isPositionReady: boolean) => ({
|
|
27
|
+
initial,
|
|
28
|
+
animate,
|
|
29
|
+
exit,
|
|
30
|
+
transition,
|
|
31
|
+
}),
|
|
32
|
+
backdrop: (open?: boolean) => ({ initial, animate, exit, transition }),
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Example Code
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { motion } from "motion/react";
|
|
40
|
+
import { motionPresets } from "@/packages/Frameworks/Motion";
|
|
41
|
+
|
|
42
|
+
function AnimatedModal({ isOpen, children }) {
|
|
43
|
+
return (
|
|
44
|
+
<AnimatePresence>
|
|
45
|
+
{isOpen && (
|
|
46
|
+
<>
|
|
47
|
+
{/* Backdrop animation */}
|
|
48
|
+
<motion.div
|
|
49
|
+
{...motionPresets.backdrop(isOpen)}
|
|
50
|
+
className="backdrop"
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
{/* Modal body animation */}
|
|
54
|
+
<motion.div {...motionPresets.modal} className="modal-content">
|
|
55
|
+
{children}
|
|
56
|
+
</motion.div>
|
|
57
|
+
</>
|
|
58
|
+
)}
|
|
59
|
+
</AnimatePresence>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Pressable Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `Pressable` framework is a versatile multipurpose wrapper component that handles user interactions such as click, touch, and hover. It dynamically identifies its role—link (`<a>`, `Link`), button (`<button>`), form control (`checkbox`, `radio`), or custom popover trigger—and renders the appropriate DOM element and accessibility attributes. It also uniformly applies Squircle shapes, motion wrapping, and theme-based styling.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- When an `href` prop is given, it internally renders as Next.js's `Link` component or a plain `<a>` tag.
|
|
10
|
+
- With `type="checkbox"` or `type="radio"`, it renders as a custom label (`<label>`) together with a visually hidden `<input>` element.
|
|
11
|
+
- With a button action or `onClick`, it renders as a `<button>`. The `popover` prop lets you declaratively write a popover trigger and inner content together.
|
|
12
|
+
- Use `themePreset` etc. to automate styling for press/hover interactions.
|
|
13
|
+
|
|
14
|
+
## Type Signatures
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import type { CSSProperties } from "react";
|
|
18
|
+
import type { LinkProps } from "next/link";
|
|
19
|
+
import type { MotionProps } from "motion/react";
|
|
20
|
+
import type { PopoverConfig } from "../Dialog/Dialog.types";
|
|
21
|
+
import type { WindProps } from "../_shared/Wind.types";
|
|
22
|
+
import type { ThemeSystemProps, BorderProps } from "../Theme/Theme.types";
|
|
23
|
+
import type { RadiusProps } from "../Theme/Radius.types";
|
|
24
|
+
|
|
25
|
+
export interface PressableProps
|
|
26
|
+
extends WindProps, ThemeSystemProps, BorderProps, RadiusProps /* ...others omitted */ {
|
|
27
|
+
href?: LinkProps["href"];
|
|
28
|
+
onClick?: (e: React.MouseEvent) => void;
|
|
29
|
+
type?: HTMLButtonElement["type"] | "checkbox" | "radio";
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
checked?: HTMLInputElement["checked"];
|
|
32
|
+
popover?: Omit<PopoverConfig, "anchorRef"> & {
|
|
33
|
+
content: React.ReactNode;
|
|
34
|
+
open?: boolean;
|
|
35
|
+
defaultOpen?: boolean;
|
|
36
|
+
onOpenChange?: (open: boolean) => void;
|
|
37
|
+
};
|
|
38
|
+
motion?: MotionProps;
|
|
39
|
+
noSquircle?: boolean; // whether to prevent Squircle corner application
|
|
40
|
+
// other various event handlers and layout properties
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Example Code
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import Pressable from "@/packages/Frameworks/Pressable/Pressable";
|
|
48
|
+
|
|
49
|
+
function Example() {
|
|
50
|
+
return (
|
|
51
|
+
<div style={{ display: "flex", gap: 16 }}>
|
|
52
|
+
{/* 1. Normal button */}
|
|
53
|
+
<Pressable themePreset="UIPrimary" onClick={() => alert("Clicked")}>
|
|
54
|
+
Primary Button
|
|
55
|
+
</Pressable>
|
|
56
|
+
|
|
57
|
+
{/* 2. Link button */}
|
|
58
|
+
<Pressable href="/about" themePreset="BaseFull" radius="R16">
|
|
59
|
+
Go to About
|
|
60
|
+
</Pressable>
|
|
61
|
+
|
|
62
|
+
{/* 3. Checkbox control */}
|
|
63
|
+
<Pressable type="checkbox" checked={true} onChange={() => {}}>
|
|
64
|
+
Toggle Checked
|
|
65
|
+
</Pressable>
|
|
66
|
+
|
|
67
|
+
{/* 4. Popover trigger combined */}
|
|
68
|
+
<Pressable
|
|
69
|
+
themePreset="UISecondary"
|
|
70
|
+
popover={{
|
|
71
|
+
content: <div style={{ padding: 16 }}>This is popover content.</div>,
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
Open Popover
|
|
75
|
+
</Pressable>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Squircle Framework
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
The `Squircle` framework is a component for rendering the "Super Ellipse" (squircle) corners mainly used in the Apple ecosystem within React applications. Using the `figma-squircle` library, it dynamically calculates and applies an SVG Path-based `clip-path`, providing smooth and soft rounded-corner design.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- Renders as a `<div>` by default, and can be changed to the desired element via the `as` prop.
|
|
10
|
+
- The `radius` prop specifies the corner roundness (can be set individually); internally observes the element size (ResizeObserver) to generate the accurate SVG `clip-path`.
|
|
11
|
+
- When a `motion` object is passed, it renders as a motion squircle component combined with framer-motion.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import type { ElementType, HTMLAttributes } from "react";
|
|
17
|
+
import type { MotionProps } from "motion/react";
|
|
18
|
+
import type { RadiusValue } from "../Theme/Radius.types";
|
|
19
|
+
|
|
20
|
+
export interface SquircleProps extends Omit<
|
|
21
|
+
HTMLAttributes<HTMLElement>,
|
|
22
|
+
"color"
|
|
23
|
+
> {
|
|
24
|
+
as?: ElementType; // element to render (default: "div")
|
|
25
|
+
radius?: RadiusValue; // corner radius (scale or pixel unit)
|
|
26
|
+
cornerRadius?: number; // hardcoded corner radius
|
|
27
|
+
cornerSmoothing?: number; // smoothing degree (default: 0.6)
|
|
28
|
+
preserveSmoothing?: boolean;
|
|
29
|
+
motion?: MotionProps; // animation properties
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Example Code
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import Squircle from "@/packages/Frameworks/Squircle";
|
|
37
|
+
|
|
38
|
+
function Card() {
|
|
39
|
+
return (
|
|
40
|
+
<Squircle
|
|
41
|
+
as="section"
|
|
42
|
+
radius="R24" // UIKit Radius system token
|
|
43
|
+
style={{ background: "white", padding: 20 }}
|
|
44
|
+
>
|
|
45
|
+
<h2>Soft-corner card</h2>
|
|
46
|
+
<p>Super Ellipse curvature applied.</p>
|
|
47
|
+
</Squircle>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|