@musecat/uikit 0.1.1 → 0.1.3

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.
Files changed (58) hide show
  1. package/.agents/references/Components/Box.md +60 -0
  2. package/.agents/references/Components/Button.md +49 -0
  3. package/.agents/references/Components/Card.md +67 -0
  4. package/.agents/references/Components/Checkbox.md +48 -0
  5. package/.agents/references/Components/CodeBox.md +31 -0
  6. package/.agents/references/Components/ContextMenu.md +82 -0
  7. package/.agents/references/Components/ContributionGraph.md +61 -0
  8. package/.agents/references/Components/DatePicker.md +92 -0
  9. package/.agents/references/Components/Divider.md +56 -0
  10. package/.agents/references/Components/Header.md +52 -0
  11. package/.agents/references/Components/Icon.md +82 -0
  12. package/.agents/references/Components/Input.md +60 -0
  13. package/.agents/references/Components/Label.md +78 -0
  14. package/.agents/references/Components/Layout.md +102 -0
  15. package/.agents/references/Components/Maps.md +63 -0
  16. package/.agents/references/Components/Nav.md +68 -0
  17. package/.agents/references/Components/Pagination.md +67 -0
  18. package/.agents/references/Components/Pill.md +75 -0
  19. package/.agents/references/Components/Profile.md +76 -0
  20. package/.agents/references/Components/Progress.md +72 -0
  21. package/.agents/references/Components/Radio.md +68 -0
  22. package/.agents/references/Components/Select.md +80 -0
  23. package/.agents/references/Components/Skeleton.md +48 -0
  24. package/.agents/references/Components/Spinner.md +62 -0
  25. package/.agents/references/Components/Text.md +73 -0
  26. package/.agents/references/Components/TimePicker.md +72 -0
  27. package/.agents/references/Components/Timeline.md +97 -0
  28. package/.agents/references/Components/Title.md +108 -0
  29. package/.agents/references/Components/Toggle.md +53 -0
  30. package/.agents/references/Components/Tooltip.md +62 -0
  31. package/.agents/references/Frameworks/DNDView.md +82 -0
  32. package/.agents/references/Frameworks/Dialog.md +109 -0
  33. package/.agents/references/Frameworks/EdgeEffect.md +64 -0
  34. package/.agents/references/Frameworks/HScrollView.md +76 -0
  35. package/.agents/references/Frameworks/ImageView.md +67 -0
  36. package/.agents/references/Frameworks/Motion.md +62 -0
  37. package/.agents/references/Frameworks/Pressable.md +79 -0
  38. package/.agents/references/Frameworks/Squircle.md +50 -0
  39. package/.agents/references/Frameworks/Theme.md +68 -0
  40. package/.agents/references/Frameworks/Toaster.md +67 -0
  41. package/.agents/references/Frameworks/View.md +81 -0
  42. package/.agents/references/Frameworks/_shared.md +74 -0
  43. package/.agents/references/Styles/Animation.md +43 -0
  44. package/.agents/references/Styles/Color.md +45 -0
  45. package/.agents/references/Styles/Font.md +37 -0
  46. package/.agents/references/Styles/Icon.md +43 -0
  47. package/.agents/references/Styles/Importer.md +19 -0
  48. package/.agents/references/Styles/System.md +27 -0
  49. package/.agents/references/Styles/Textstyle.md +45 -0
  50. package/.agents/references/Styles/Theme.md +51 -0
  51. package/.agents/references/Styles/Viewport-global.md +42 -0
  52. package/.agents/references/Styles/Viewport.md +42 -0
  53. package/AGENTS.md +54 -0
  54. package/CLAUDE.md +1 -0
  55. package/README.md +4 -0
  56. package/package.json +4 -1
  57. package/packages/Styles/_icon.scss +2 -0
  58. 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
+ ```