@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,60 @@
|
|
|
1
|
+
# Input
|
|
2
|
+
|
|
3
|
+
## 1. Purpose
|
|
4
|
+
|
|
5
|
+
- A single text input form component.
|
|
6
|
+
- Role: Combines the native HTML `input` element with the UIKit design system, theme props, and a Label (title, hint, etc.) wrapper.
|
|
7
|
+
|
|
8
|
+
## 2. Usage Logic
|
|
9
|
+
|
|
10
|
+
- Inherits standard input attributes like `type`, `value`, `placeholder`, `disabled`, `readOnly` as-is.
|
|
11
|
+
- Passing `title`, `required`, `hint` props automatically wraps it internally with the `Label` component to render the title and validation message.
|
|
12
|
+
- Supports the `prefix` prop: displays left-side text inside the input (e.g., `@`, `#`, `₩`, etc.).
|
|
13
|
+
- On error, passing `hint={{ type: "error", text: "..." }}` automatically enables the ARIA-based `aria-invalid`.
|
|
14
|
+
|
|
15
|
+
## 3. Type Signatures
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import type { LabelSharedProps } from "../Label/Label.types";
|
|
19
|
+
|
|
20
|
+
export interface InputProps
|
|
21
|
+
extends
|
|
22
|
+
Omit<
|
|
23
|
+
React.InputHTMLAttributes<HTMLInputElement>,
|
|
24
|
+
"prefix" | keyof LabelSharedProps
|
|
25
|
+
>,
|
|
26
|
+
LabelSharedProps {
|
|
27
|
+
value?: string | number;
|
|
28
|
+
type?: string;
|
|
29
|
+
placeholder?: string;
|
|
30
|
+
prefix?: React.ReactNode;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
_(LabelSharedProps includes `title`, `required`, `hint`, ThemeSystemProps, etc.)_
|
|
35
|
+
|
|
36
|
+
## 4. Example Code
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import Input from "@/packages/Components/Input/Input";
|
|
40
|
+
|
|
41
|
+
export default function Example() {
|
|
42
|
+
return (
|
|
43
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "16px" }}>
|
|
44
|
+
<Input
|
|
45
|
+
title="Email Address"
|
|
46
|
+
type="email"
|
|
47
|
+
placeholder="example@mail.com"
|
|
48
|
+
required
|
|
49
|
+
/>
|
|
50
|
+
|
|
51
|
+
<Input
|
|
52
|
+
title="Nickname"
|
|
53
|
+
prefix="@"
|
|
54
|
+
placeholder="username"
|
|
55
|
+
hint={{ type: "error", text: "This nickname is already in use." }}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Label
|
|
2
|
+
|
|
3
|
+
## 1. Purpose
|
|
4
|
+
|
|
5
|
+
- A form element container and control wrapper.
|
|
6
|
+
- Role: Wraps input fields (Input, Select, DatePicker, etc.) and is responsible for the title, required marker (*), bottom hint (error, info, etc.) messages, and common outline styling (theme and padding).
|
|
7
|
+
|
|
8
|
+
## 2. Usage Logic
|
|
9
|
+
|
|
10
|
+
- Place the form control component to wrap inside `children`.
|
|
11
|
+
- Wrapped by an outer `Pressable` wrapper so that clicking anywhere in the field area transfers focus to the inner form via `htmlFor` control.
|
|
12
|
+
- Based on the `hint` object (`type`: "error", "success", "info", "warning", `text`), the bottom icon and text color are automatically mapped and rendered.
|
|
13
|
+
- Frequently used internally to keep form interface specs consistent when creating or extending components.
|
|
14
|
+
|
|
15
|
+
## 3. Type Signatures
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import type {
|
|
19
|
+
ThemeSystemProps,
|
|
20
|
+
BorderProps,
|
|
21
|
+
RadiusProps,
|
|
22
|
+
} from "../../Frameworks/Theme/Theme.types";
|
|
23
|
+
|
|
24
|
+
export interface LabelProps extends ThemeSystemProps, BorderProps, RadiusProps {
|
|
25
|
+
"data-color-mode"?: string;
|
|
26
|
+
children?: React.ReactNode;
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: React.CSSProperties;
|
|
29
|
+
|
|
30
|
+
// HTML form attributes
|
|
31
|
+
htmlFor?: string;
|
|
32
|
+
hintId?: string;
|
|
33
|
+
|
|
34
|
+
// Content
|
|
35
|
+
title?: string;
|
|
36
|
+
required?: boolean;
|
|
37
|
+
hint?: {
|
|
38
|
+
type: "info" | "error" | "warning" | "success";
|
|
39
|
+
text: React.ReactNode;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// State
|
|
43
|
+
readOnly?: boolean;
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
cursor?: React.CSSProperties["cursor"];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Omit 'children', 'htmlFor', 'hintId' for consumer forwarding
|
|
49
|
+
export type LabelSharedProps = Omit<
|
|
50
|
+
LabelProps,
|
|
51
|
+
"children" | "htmlFor" | "hintId"
|
|
52
|
+
>;
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 4. Example Code
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import Label from "@/packages/Components/Label/Label";
|
|
59
|
+
import Checkbox from "@/packages/Components/Checkbox/Checkbox"; // virtual import
|
|
60
|
+
|
|
61
|
+
export default function Example() {
|
|
62
|
+
return (
|
|
63
|
+
<Label
|
|
64
|
+
htmlFor="terms-agree"
|
|
65
|
+
title="Agree to Terms"
|
|
66
|
+
required
|
|
67
|
+
hint={{ type: "info", text: "Required to use the service." }}
|
|
68
|
+
themePreset="BaseFull"
|
|
69
|
+
radius="Regular"
|
|
70
|
+
>
|
|
71
|
+
<div style={{ display: "flex", gap: "8px", alignItems: "center" }}>
|
|
72
|
+
<Checkbox id="terms-agree" />
|
|
73
|
+
<span>I agree</span>
|
|
74
|
+
</div>
|
|
75
|
+
</Label>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Layout Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Acts as a container that establishes the common structure of applications and pages. Provides the base page layout (`Layout`), grid-based arrangement (`Layout.Grid`, `Layout.Section`), and a layout specialized for documents or posts (`DocsLayout`) to help build consistent UI composition and structure.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **`Layout`**: Used as the top-level container of a page, composing the overall page frame via props such as `title`, `header`, `backgroundImage`, `children`.
|
|
10
|
+
- **`Layout.Grid` & `Layout.Section`**: Used under `Layout` to split content into a grid (`Grid`) or group it into a specific area (`Section`) with a title.
|
|
11
|
+
- **`Layout.docs`**: A dedicated layout for rendering document/post-style content such as a cover image, author info (profile), and creation date.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
// Layout.types.ts
|
|
17
|
+
export interface BackgroundImageValue {
|
|
18
|
+
height?: UIKitSizeValue;
|
|
19
|
+
src?: string;
|
|
20
|
+
filter?: CSSProperties["filter"];
|
|
21
|
+
margin?: BackgroundMarginValue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface LayoutProps {
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
title?: React.ReactNode;
|
|
27
|
+
caption?: React.ReactNode;
|
|
28
|
+
titleType?: TitleProps["titleType"];
|
|
29
|
+
titleFontType?: TextProps["fontType"];
|
|
30
|
+
mobileTitleShown?: boolean;
|
|
31
|
+
header?: React.ReactNode;
|
|
32
|
+
backgroundImage?: string | BackgroundImageValue;
|
|
33
|
+
// ...
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface LayoutGridViewProps {
|
|
37
|
+
children?: React.ReactNode;
|
|
38
|
+
ratio?: string;
|
|
39
|
+
gap?: ViewProps["gap"];
|
|
40
|
+
groupGap?: ViewProps["gap"];
|
|
41
|
+
// ...
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface LayoutSectionProps extends ViewProps {
|
|
45
|
+
group?: string;
|
|
46
|
+
title?: React.ReactNode | TitleProps["title"];
|
|
47
|
+
titleType?: TitleProps["titleType"];
|
|
48
|
+
// ...
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Layout.docs.types.ts
|
|
52
|
+
export interface DocsLayoutProps {
|
|
53
|
+
children?: React.ReactNode;
|
|
54
|
+
image?: string;
|
|
55
|
+
header?: React.ReactNode;
|
|
56
|
+
author?: ProfileProps;
|
|
57
|
+
createdBy?: string;
|
|
58
|
+
title?: React.ReactNode;
|
|
59
|
+
// ...
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Example Code
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
import Layout from "@/packages/Components/Layout/Layout";
|
|
67
|
+
import DocsLayout from "@/packages/Components/Layout/Layout.docs";
|
|
68
|
+
|
|
69
|
+
// Basic layout and section split
|
|
70
|
+
export function MyPage() {
|
|
71
|
+
return (
|
|
72
|
+
<Layout
|
|
73
|
+
title="Dashboard"
|
|
74
|
+
backgroundImage={{ src: "/bg.png", height: "300px" }}
|
|
75
|
+
>
|
|
76
|
+
<Layout.Grid ratio="1fr 1fr" gap={16}>
|
|
77
|
+
<Layout.Section title="Recent News" titleType="Title2">
|
|
78
|
+
<div>News content 1</div>
|
|
79
|
+
<div>News content 2</div>
|
|
80
|
+
</Layout.Section>
|
|
81
|
+
<Layout.Section title="Statistics">
|
|
82
|
+
<div>Chart area</div>
|
|
83
|
+
</Layout.Section>
|
|
84
|
+
</Layout.Grid>
|
|
85
|
+
</Layout>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Document-style layout
|
|
90
|
+
export function MyPost() {
|
|
91
|
+
return (
|
|
92
|
+
<DocsLayout
|
|
93
|
+
title="Component Docs"
|
|
94
|
+
author={{ displayName: "Hong Gildong", avatarUrl: "..." }}
|
|
95
|
+
createdBy="2026-07-16"
|
|
96
|
+
image="/cover.png"
|
|
97
|
+
>
|
|
98
|
+
Document body content goes here.
|
|
99
|
+
</DocsLayout>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Maps Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A component (`MapOSM`) that renders a custom interactive map based on OpenStreetMap (OSM) using the `maplibre-gl` library. Provides core map-related UI/UX such as marker display, drag/zoom controls, and coordinate selection (click events).
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **`MapOSM`**: Injects `lat` (latitude) and `lon` (longitude) values to set the map's initial center and marker position. Map size is controlled via `width` and `height`.
|
|
10
|
+
- When `interactive` mode is enabled, user zoom, panning, and rotation become available.
|
|
11
|
+
- Providing the `onMapPick` callback lets you receive the coordinates (latitude, longitude) of the clicked location (usable as a coordinate picker).
|
|
12
|
+
- Utility logic in `MapOSM.shared.ts` (`resolveSafeMapStyle`, etc.) safely applies style filters or controls the 3D view.
|
|
13
|
+
|
|
14
|
+
## Type Signatures
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// MapOSM.types.ts
|
|
18
|
+
import type maplibregl from "maplibre-gl";
|
|
19
|
+
import type { CSSProperties } from "react";
|
|
20
|
+
|
|
21
|
+
export interface MapOSMProps {
|
|
22
|
+
lat: number | string;
|
|
23
|
+
lon: number | string;
|
|
24
|
+
onMapPick?: (lat: number | string, lon: number | string) => void;
|
|
25
|
+
height?: string;
|
|
26
|
+
width?: string;
|
|
27
|
+
className?: string;
|
|
28
|
+
style?: CSSProperties;
|
|
29
|
+
mapClassName?: string;
|
|
30
|
+
mapStyle?: CSSProperties;
|
|
31
|
+
interactive?: boolean; // whether zoom/drag is enabled
|
|
32
|
+
disable3D?: boolean; // disable 3D terrain
|
|
33
|
+
showNavigationControl?: boolean; // show navigation control (top-right zoom control, etc.)
|
|
34
|
+
mapOptions?: Partial<maplibregl.MapOptions>;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Example Code
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import MapOSM from "@/packages/Components/Maps/OSM/MapOSM";
|
|
42
|
+
import { useState } from "react";
|
|
43
|
+
|
|
44
|
+
export function LocationPicker() {
|
|
45
|
+
const [location, setLocation] = useState({ lat: 37.5665, lon: 126.978 }); // Seoul City Hall default
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div style={{ padding: "20px" }}>
|
|
49
|
+
<h3>Select Location</h3>
|
|
50
|
+
<MapOSM
|
|
51
|
+
lat={location.lat}
|
|
52
|
+
lon={location.lon}
|
|
53
|
+
height="500px"
|
|
54
|
+
interactive={true}
|
|
55
|
+
onMapPick={(lat, lon) => {
|
|
56
|
+
console.log(`Selected location: lat ${lat}, lon ${lon}`);
|
|
57
|
+
setLocation({ lat: Number(lat), lon: Number(lon) });
|
|
58
|
+
}}
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Nav Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Provides a UI for choosing one (or several) option among multiple choices such as tabs, radio button groups, and navigation menus. Supports a visual selection effect (sliding indicator) along with a smooth item selection method via drag-and-drop gestures.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **`Nav` component**: Passes options (icon, text, value, etc.) via the `items` array to render the UI. Supports both Controlled (`value`, `onChange`) and Uncontrolled (`defaultValue`) modes.
|
|
10
|
+
- **`useNavIndicator` (internal hook)**: Tracks the currently selected item's position and calculates `transform` and `width` so the highlight background (Indicator) moves smoothly.
|
|
11
|
+
- **`useNavDrag` (internal hook)**: Manages the logic that, while dragging across buttons with mouse or touch (Drag Selection), dynamically changes the indicator to match the hovered value and commits the final selection at drop time.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
// Nav.types.ts
|
|
17
|
+
import type { ReactNode } from "react";
|
|
18
|
+
import type { PressableProps } from "../../Frameworks/Pressable/Pressable.types";
|
|
19
|
+
import type { IconProps } from "../Icon/Icon.types";
|
|
20
|
+
|
|
21
|
+
export interface NavOption extends Omit<PressableProps, "title"> {
|
|
22
|
+
checked?: boolean;
|
|
23
|
+
icon?: IconProps;
|
|
24
|
+
title?: ReactNode;
|
|
25
|
+
value?: string | number; // value returned/compared on selection
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface NavProps extends RadiusProps {
|
|
29
|
+
className?: string;
|
|
30
|
+
name?: string; // radio group name
|
|
31
|
+
radio?: boolean; // enable radio mode (exclusive single selection when true)
|
|
32
|
+
dragSelection?: boolean; // allow selection change via drag
|
|
33
|
+
dragSelectionCommit?: "change" | "end";
|
|
34
|
+
value?: string | number;
|
|
35
|
+
defaultValue?: string | number;
|
|
36
|
+
onChange?: (value: string | number) => void;
|
|
37
|
+
items: NavOption[];
|
|
38
|
+
// ...sizing and theme props
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Example Code
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import Nav from "@/packages/Components/Nav/Nav";
|
|
46
|
+
import { useState } from "react";
|
|
47
|
+
|
|
48
|
+
export function TabNavigation() {
|
|
49
|
+
const [activeTab, setActiveTab] = useState<string>("home");
|
|
50
|
+
|
|
51
|
+
const items = [
|
|
52
|
+
{ title: "Home", value: "home", icon: { icon: "iHome" } },
|
|
53
|
+
{ title: "Explore", value: "explore", icon: { icon: "iSearch" } },
|
|
54
|
+
{ title: "Profile", value: "profile", icon: { icon: "iPerson" } },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Nav
|
|
59
|
+
radio={true}
|
|
60
|
+
dragSelection={true}
|
|
61
|
+
value={activeTab}
|
|
62
|
+
onChange={(val) => setActiveTab(val as string)}
|
|
63
|
+
items={items}
|
|
64
|
+
radius="Round"
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Pagination Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A pagination controller that helps navigate data or lists split across multiple pages. Along with previous/next and first/last navigation buttons, it provides an `input` area where users can directly enter a desired page number to jump quickly.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **`Pagination`**: Receives `page` (current page) and `total` (total page count) props to compose the navigation bar.
|
|
10
|
+
- Internally manages an `input` field for numeric entry, applying a debounce timer (350ms) so it does not jump immediately while the user is typing, but waits for input completion (or Enter key) before firing the `onChange` event.
|
|
11
|
+
- Invalid page input is automatically clamped to the minimum (1) or maximum (`total`) value.
|
|
12
|
+
- For i18n, internally uses the `Word()` hook to provide default labels ("Previous", "Next", etc.), and custom labels can also be injected directly.
|
|
13
|
+
|
|
14
|
+
## Type Signatures
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// Pagination.types.ts
|
|
18
|
+
import type {
|
|
19
|
+
BorderProps,
|
|
20
|
+
ThemeSystemProps,
|
|
21
|
+
} from "../../Frameworks/Theme/Theme.types";
|
|
22
|
+
|
|
23
|
+
export interface PaginationProps extends ThemeSystemProps, BorderProps {
|
|
24
|
+
page: number; // currently selected page number
|
|
25
|
+
total: number; // total page count (last page number)
|
|
26
|
+
onChange?: (page: number) => void; // page move event callback
|
|
27
|
+
disabled?: boolean; // disable the entire component
|
|
28
|
+
|
|
29
|
+
// Label customization (optional)
|
|
30
|
+
previousLabel?: string;
|
|
31
|
+
nextLabel?: string;
|
|
32
|
+
navigationLabel?: string;
|
|
33
|
+
getPageLabel?: (page: number, isCurrent: boolean) => string;
|
|
34
|
+
|
|
35
|
+
className?: string;
|
|
36
|
+
style?: React.CSSProperties;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Example Code
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import Pagination from "@/packages/Components/Pagination/Pagination";
|
|
44
|
+
import { useState } from "react";
|
|
45
|
+
|
|
46
|
+
export function DataList() {
|
|
47
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
48
|
+
const totalPages = 25;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div style={{ padding: "20px" }}>
|
|
52
|
+
<ul>
|
|
53
|
+
{/* Render data list logic matching the current page */}
|
|
54
|
+
<li>Item 1</li>
|
|
55
|
+
<li>Item 2</li>
|
|
56
|
+
</ul>
|
|
57
|
+
|
|
58
|
+
<Pagination
|
|
59
|
+
page={currentPage}
|
|
60
|
+
total={totalPages}
|
|
61
|
+
onChange={(newPage) => setCurrentPage(newPage)}
|
|
62
|
+
themePreset="UIPrimary"
|
|
63
|
+
/>
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Pill Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A UI element (capsule/pill shape) used as a keyword, tag, status badge, or small rounded capsule button. Flexibly supports combinations of icon and text, loading state display, and text ellipsis handling.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- Built on the `Pressable` framework component, so it easily converts from a simple badge form to a touch/clickable interactive button.
|
|
10
|
+
- `text`, `icon`, `rightIcon` make it easy to arrange a left icon, center text, and right supplementary icon.
|
|
11
|
+
- When the `loading` prop is true, a loading spinner icon is automatically shown in the right area.
|
|
12
|
+
- The `ellipsis` option truncates text with `...` without wrapping in narrow spaces.
|
|
13
|
+
|
|
14
|
+
## Type Signatures
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// Pill.types.ts
|
|
18
|
+
import type { IconProps } from "../Icon/Icon.types";
|
|
19
|
+
import type { PressableProps } from "../../Frameworks/Pressable/Pressable.types";
|
|
20
|
+
import type { TextProps } from "../Text/Text.types";
|
|
21
|
+
import type { RadiusProps } from "../../Frameworks/Theme/Radius.types";
|
|
22
|
+
import type {
|
|
23
|
+
ThemeSystemProps,
|
|
24
|
+
BorderProps,
|
|
25
|
+
} from "../../Frameworks/Theme/Theme.types";
|
|
26
|
+
|
|
27
|
+
export interface PillProps extends ThemeSystemProps, RadiusProps, BorderProps {
|
|
28
|
+
text?: React.ReactNode;
|
|
29
|
+
icon?: IconProps; // left icon
|
|
30
|
+
rightIcon?: IconProps; // right icon
|
|
31
|
+
|
|
32
|
+
pressable?: PressableProps; // Pressable props including click events
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
loading?: boolean; // enable loading state (show spinner)
|
|
35
|
+
|
|
36
|
+
ellipsis?: boolean; // text ellipsis handling
|
|
37
|
+
shouldWrapText?: boolean; // whether to wrap text (default true)
|
|
38
|
+
|
|
39
|
+
textType?: TextProps["type"];
|
|
40
|
+
textSize?: TextProps["size"];
|
|
41
|
+
textWeight?: TextProps["weight"];
|
|
42
|
+
iconSize?: UIKitSizeValue;
|
|
43
|
+
|
|
44
|
+
checkedThemePreset?: ThemeSystemProps["themePreset"];
|
|
45
|
+
// ... other style and layout related Props
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Example Code
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import Pill from "@/packages/Components/Pill/Pill";
|
|
53
|
+
|
|
54
|
+
export function TagList() {
|
|
55
|
+
return (
|
|
56
|
+
<div style={{ display: "flex", gap: "8px" }}>
|
|
57
|
+
{/* Basic text pill */}
|
|
58
|
+
<Pill text="Design" themePreset="BaseFull" radius="Round" />
|
|
59
|
+
|
|
60
|
+
{/* Pill with icon, clickable */}
|
|
61
|
+
<Pill
|
|
62
|
+
text="Apply Filter"
|
|
63
|
+
icon={{ icon: "iFilter" }}
|
|
64
|
+
themePreset="BlueSolid"
|
|
65
|
+
pressable={{
|
|
66
|
+
onClick: () => console.log("Filter clicked"),
|
|
67
|
+
}}
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
{/* Loading state pill */}
|
|
71
|
+
<Pill text="Saving" loading={true} disabled={true} />
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Profile Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A component that summarizes and renders a user's profile information (name, avatar, identifier, badge, affiliation role, etc.). In addition to fallback image (default icon) handling based on avatar presence, it also includes an advanced feature that displays expanded profile info in a popover layer on click.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **Inline rendering (`ProfileInlineContent`)**: Shows the most basic profile form exposed externally. Renders the avatar photo, name (`displayName`), sub-text (`username`), and certification mark (Certified).
|
|
10
|
+
- **Popover rendering (`ProfilePopoverContent`)**: When `profileHref` or the `popover` prop is passed, a detailed info popover is shown on click/hover. This may include extended actions such as join date, detailed Role list, and user report (`canReport`).
|
|
11
|
+
- **Shared logic (`Profile.shared.ts`)**: Provides the `getProfileAvatarIconProps` utility function, which, when an actual profile image URL (`avatarUrl`) exists, generates that image, and otherwise generates the default person icon (`iPerson`) with appropriate size and padding.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
// Profile.types.ts
|
|
17
|
+
export type ProfileRole = {
|
|
18
|
+
label: string;
|
|
19
|
+
color?: ThemePaint;
|
|
20
|
+
icon?: string;
|
|
21
|
+
iconFill?: boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type ProfileSizeOptions = {
|
|
25
|
+
avatar?: number; // avatar size
|
|
26
|
+
textType?: TextProps["type"];
|
|
27
|
+
textSize?: UIKitSizeValue;
|
|
28
|
+
badge?: number; // badge (certification) size
|
|
29
|
+
gap?: UIKitSizeValue;
|
|
30
|
+
fallbackPadding?: UIKitSizeValue; // padding when using default icon
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export interface ProfileProps {
|
|
34
|
+
displayName: string;
|
|
35
|
+
username?: string;
|
|
36
|
+
avatarUrl?: string | null;
|
|
37
|
+
avatarLoading?: "eager" | "lazy";
|
|
38
|
+
bio?: string;
|
|
39
|
+
isCertified?: boolean; // presence of official certification mark
|
|
40
|
+
certifiedAt?: string;
|
|
41
|
+
roles?: ProfileRole[]; // user's multiple roles list
|
|
42
|
+
joinedAtText?: string;
|
|
43
|
+
|
|
44
|
+
profileHref?: string | null; // URL to navigate to on popover click
|
|
45
|
+
canReport?: boolean; // whether report feature is enabled
|
|
46
|
+
onReport?: () => void;
|
|
47
|
+
|
|
48
|
+
extended?: boolean; // enable inline display of supplementary info like username
|
|
49
|
+
size?: ProfileSizeOptions;
|
|
50
|
+
popover?: React.ReactNode; // inject custom popover content
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Example Code
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import Profile from "@/packages/Components/Profile/Profile";
|
|
58
|
+
|
|
59
|
+
export function UserHeader() {
|
|
60
|
+
return (
|
|
61
|
+
<Profile
|
|
62
|
+
displayName="Kim Coding"
|
|
63
|
+
username="kim_code"
|
|
64
|
+
avatarUrl="https://example.com/avatar.png"
|
|
65
|
+
isCertified={true}
|
|
66
|
+
bio="Frontend developer."
|
|
67
|
+
joinedAtText="Joined 2023"
|
|
68
|
+
roles={[{ label: "Admin", color: "Blue3" }]}
|
|
69
|
+
profileHref="/users/kim_code"
|
|
70
|
+
canReport={true}
|
|
71
|
+
onReport={() => console.log("Report user")}
|
|
72
|
+
extended={true} // expose username (@kim_code) even inline
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Progress Component Documentation
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
A linear progress bar component that visualizes task progress as a percentage. It can also render an indeterminate spinner-style infinite loading state for tasks with unknown duration.
|
|
6
|
+
|
|
7
|
+
## Usage Logic
|
|
8
|
+
|
|
9
|
+
- **Determinate state**: When `value`, `min`, `max` are passed, the progress rate (percentage) is calculated by the formula `(value - min) / (max - min) * 100`, adjusting the width of the inner indicator view (using the `--progress-percent` CSS variable).
|
|
10
|
+
- **Indeterminate state**: When `indeterminate={true}` is set, instead of a percentage-based progress bar, the inner `Spinner` component is rendered directly to indicate an infinite loading state.
|
|
11
|
+
- Value clamping: Even if the passed `value` is out of range, it is safely adjusted between `min` and `max` automatically.
|
|
12
|
+
|
|
13
|
+
## Type Signatures
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
// Progress.types.ts
|
|
17
|
+
import { RadiusProps } from "@/packages/Frameworks/Theme/Radius.types";
|
|
18
|
+
import type {
|
|
19
|
+
ThemeBackgroundPaint,
|
|
20
|
+
ThemePaint,
|
|
21
|
+
} from "../../Frameworks/Theme/Theme.types";
|
|
22
|
+
|
|
23
|
+
export interface ProgressProps extends RadiusProps {
|
|
24
|
+
value?: number; // current progress value (default: 0)
|
|
25
|
+
min?: number; // minimum value (default: 0)
|
|
26
|
+
max?: number; // maximum value (default: 100)
|
|
27
|
+
indeterminate?: boolean; // whether in indeterminate (infinite loading) state
|
|
28
|
+
|
|
29
|
+
background?: ThemeBackgroundPaint; // track (background) color theme
|
|
30
|
+
color?: ThemePaint; // indicator (progress bar) color theme
|
|
31
|
+
|
|
32
|
+
className?: string;
|
|
33
|
+
trackClassName?: string;
|
|
34
|
+
indicatorClassName?: string;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Example Code
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import Progress from "@/packages/Components/Progress/Progress";
|
|
42
|
+
|
|
43
|
+
export function FileUploadStatus({
|
|
44
|
+
progressPercentage,
|
|
45
|
+
isUploading,
|
|
46
|
+
isPreparing,
|
|
47
|
+
}) {
|
|
48
|
+
// Preparing, so total length unknown (indeterminate state)
|
|
49
|
+
if (isPreparing) {
|
|
50
|
+
return <Progress indeterminate={true} />;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Uploading (determinate state)
|
|
54
|
+
if (isUploading) {
|
|
55
|
+
return (
|
|
56
|
+
<div style={{ width: "300px" }}>
|
|
57
|
+
<span>Uploading: {progressPercentage}%</span>
|
|
58
|
+
<Progress
|
|
59
|
+
value={progressPercentage}
|
|
60
|
+
min={0}
|
|
61
|
+
max={100}
|
|
62
|
+
color="BlueSolid"
|
|
63
|
+
background="Base6TP6"
|
|
64
|
+
radius="Round"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return <span>Upload complete</span>;
|
|
71
|
+
}
|
|
72
|
+
```
|