@suphark/ui 0.6.1 → 0.7.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/CHANGELOG.md +24 -0
- package/package.json +1 -1
- package/src/components/app-shell/app-shell.tsx +6 -7
- package/src/components/app-shell/command-palette.tsx +256 -0
- package/src/components/app-shell/index.ts +11 -0
- package/src/components/app-shell/organization-switcher.tsx +150 -0
- package/src/components/app-shell/user-menu.tsx +8 -3
- package/src/components/data-table/data-table.tsx +34 -26
- package/src/components/data-table/types.ts +4 -0
- package/src/components/shared/action-form.tsx +12 -3
- package/src/components/shared/calendar-month-grid.tsx +182 -0
- package/src/components/shared/form/labeled-field.tsx +21 -0
- package/src/components/shared/form-dialog.tsx +12 -3
- package/src/components/shared/form-message.tsx +25 -1
- package/src/components/shared/icon-picker.tsx +192 -0
- package/src/components/shared/progress-bar.tsx +83 -0
- package/src/components/shared/selection-button.tsx +29 -0
- package/src/components/shared/theme/theme-menu-items.tsx +31 -14
- package/src/components/shared/ui-text.tsx +41 -0
- package/src/index.ts +22 -1
|
@@ -9,32 +9,49 @@ import {
|
|
|
9
9
|
import { MonitorIcon, MoonIcon, SunIcon } from "lucide-react";
|
|
10
10
|
import { useTheme } from "next-themes";
|
|
11
11
|
import type { ReactNode } from "react";
|
|
12
|
+
import { useUiText } from "../ui-text";
|
|
12
13
|
import type { Theme } from "./theme-provider";
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const ICONS: Record<Theme, ReactNode> = {
|
|
16
|
+
light: <SunIcon />,
|
|
17
|
+
dark: <MoonIcon />,
|
|
18
|
+
system: <MonitorIcon />,
|
|
19
|
+
};
|
|
20
|
+
const ORDER: Theme[] = ["light", "dark", "system"];
|
|
19
21
|
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* กลุ่มตัวเลือกธีมสำหรับใส่ใน DropdownMenu (เช่นเมนูผู้ใช้) — ยกจาก Pi Auth มาบน next-themes
|
|
24
|
+
* ข้อความค่าเริ่มต้นจาก `UiText.theme`; `onThemeChange` ให้แอปบันทึกธีมเป็น preference ของบัญชี (ซิงก์ข้ามเครื่อง)
|
|
25
|
+
*/
|
|
21
26
|
export function ThemeMenuItems({
|
|
22
|
-
label
|
|
27
|
+
label,
|
|
23
28
|
labels,
|
|
29
|
+
onThemeChange,
|
|
24
30
|
}: {
|
|
25
31
|
label?: ReactNode;
|
|
26
|
-
/** ข้อความแต่ละตัวเลือก (
|
|
32
|
+
/** ข้อความแต่ละตัวเลือก (ค่าเริ่มต้นจาก UiText.theme / ไทย) */
|
|
27
33
|
labels?: Partial<Record<Theme, ReactNode>>;
|
|
34
|
+
/** เรียกหลัง setTheme — เช่น server action บันทึก preference */
|
|
35
|
+
onThemeChange?: (theme: Theme) => void | Promise<void>;
|
|
28
36
|
}) {
|
|
29
37
|
const { theme = "system", setTheme } = useTheme();
|
|
38
|
+
const text = useUiText().theme;
|
|
30
39
|
return (
|
|
31
40
|
<DropdownMenuGroup>
|
|
32
|
-
<DropdownMenuLabel className="text-muted-foreground">
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
<DropdownMenuLabel className="text-muted-foreground">
|
|
42
|
+
{label ?? text?.label ?? "ธีม"}
|
|
43
|
+
</DropdownMenuLabel>
|
|
44
|
+
<DropdownMenuRadioGroup
|
|
45
|
+
value={theme}
|
|
46
|
+
onValueChange={(v) => {
|
|
47
|
+
setTheme(v as Theme);
|
|
48
|
+
void onThemeChange?.(v as Theme);
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{ORDER.map((value) => (
|
|
52
|
+
<DropdownMenuRadioItem key={value} value={value}>
|
|
53
|
+
{ICONS[value]}
|
|
54
|
+
{labels?.[value] ?? text?.[value] ?? value}
|
|
38
55
|
</DropdownMenuRadioItem>
|
|
39
56
|
))}
|
|
40
57
|
</DropdownMenuRadioGroup>
|
|
@@ -30,6 +30,23 @@ export interface UiText {
|
|
|
30
30
|
chooseTitle?: string;
|
|
31
31
|
/** DialogsProvider: หัวกล่อง checklist (optional — ค่าเริ่มต้น "เลือกรายการ") */
|
|
32
32
|
checklistTitle?: string;
|
|
33
|
+
/** CommandPalette (optional — ค่าเริ่มต้นไทยในตัว) */
|
|
34
|
+
palette?: Partial<{
|
|
35
|
+
placeholder: string;
|
|
36
|
+
title: string;
|
|
37
|
+
description: string;
|
|
38
|
+
empty: string;
|
|
39
|
+
searching: string;
|
|
40
|
+
pages: string;
|
|
41
|
+
}>;
|
|
42
|
+
/** OrganizationSwitcher (optional) */
|
|
43
|
+
switcher?: Partial<{ choose: string; organization: string }>;
|
|
44
|
+
/** UserMenu: aria-label ปุ่มเปิดเมนู (optional — "เมนูผู้ใช้") */
|
|
45
|
+
userMenu?: string;
|
|
46
|
+
/** UserMenu: ปุ่มออกจากระบบ (optional — "ออกจากระบบ") */
|
|
47
|
+
signOut?: string;
|
|
48
|
+
/** ThemeMenuItems: หัวกลุ่ม + ตัวเลือก (optional) */
|
|
49
|
+
theme?: Partial<{ label: string; light: string; dark: string; system: string }>;
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
export const UI_TEXT_TH: UiText = {
|
|
@@ -50,6 +67,18 @@ export const UI_TEXT_TH: UiText = {
|
|
|
50
67
|
promptTitle: "กรอกข้อมูล",
|
|
51
68
|
chooseTitle: "เลือกการทำรายการ",
|
|
52
69
|
checklistTitle: "เลือกรายการ",
|
|
70
|
+
palette: {
|
|
71
|
+
placeholder: "ค้นหาหรือสั่งงาน…",
|
|
72
|
+
title: "ค้นหา",
|
|
73
|
+
description: "พิมพ์เพื่อค้นหาหน้าและข้อมูล",
|
|
74
|
+
empty: "ไม่พบผลลัพธ์",
|
|
75
|
+
searching: "กำลังค้นหา…",
|
|
76
|
+
pages: "หน้า",
|
|
77
|
+
},
|
|
78
|
+
switcher: { choose: "เลือกองค์กร", organization: "องค์กร" },
|
|
79
|
+
userMenu: "เมนูผู้ใช้",
|
|
80
|
+
signOut: "ออกจากระบบ",
|
|
81
|
+
theme: { label: "ธีม", light: "สว่าง", dark: "มืด", system: "ตามระบบ" },
|
|
53
82
|
};
|
|
54
83
|
|
|
55
84
|
export const UI_TEXT_EN: UiText = {
|
|
@@ -70,6 +99,18 @@ export const UI_TEXT_EN: UiText = {
|
|
|
70
99
|
promptTitle: "Input required",
|
|
71
100
|
chooseTitle: "Choose an action",
|
|
72
101
|
checklistTitle: "Choose options",
|
|
102
|
+
palette: {
|
|
103
|
+
placeholder: "Search or jump to…",
|
|
104
|
+
title: "Search",
|
|
105
|
+
description: "Type to search pages and records",
|
|
106
|
+
empty: "No results",
|
|
107
|
+
searching: "Searching…",
|
|
108
|
+
pages: "Pages",
|
|
109
|
+
},
|
|
110
|
+
switcher: { choose: "Choose organization", organization: "Organization" },
|
|
111
|
+
userMenu: "User menu",
|
|
112
|
+
signOut: "Sign out",
|
|
113
|
+
theme: { label: "Theme", light: "Light", dark: "Dark", system: "System" },
|
|
73
114
|
};
|
|
74
115
|
|
|
75
116
|
const UiTextContext = createContext<UiText>(UI_TEXT_TH);
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,14 @@ export type { DateRange } from "react-day-picker";
|
|
|
15
15
|
export { toast } from "sonner";
|
|
16
16
|
export { ActionForm } from "./components/shared/action-form";
|
|
17
17
|
export * from "./components/shared/button";
|
|
18
|
+
export {
|
|
19
|
+
type CalendarDayContext,
|
|
20
|
+
type CalendarDayState,
|
|
21
|
+
CalendarMonthGrid,
|
|
22
|
+
type CalendarMonthGridProps,
|
|
23
|
+
WEEKDAYS_EN,
|
|
24
|
+
WEEKDAYS_TH,
|
|
25
|
+
} from "./components/shared/calendar-month-grid";
|
|
18
26
|
export { ClientRedirect } from "./components/shared/client-redirect";
|
|
19
27
|
export { Combobox } from "./components/shared/combobox";
|
|
20
28
|
export {
|
|
@@ -60,7 +68,18 @@ export {
|
|
|
60
68
|
type SimpleSelectOptions,
|
|
61
69
|
type SimpleSelectProps,
|
|
62
70
|
} from "./components/shared/form/simple-select";
|
|
63
|
-
export {
|
|
71
|
+
export {
|
|
72
|
+
type FormAction,
|
|
73
|
+
FormMessage,
|
|
74
|
+
type FormRenderContext,
|
|
75
|
+
type FormState,
|
|
76
|
+
} from "./components/shared/form-message";
|
|
77
|
+
export {
|
|
78
|
+
IconPicker,
|
|
79
|
+
type IconPickerItem,
|
|
80
|
+
type IconPickerProps,
|
|
81
|
+
type IconPickerText,
|
|
82
|
+
} from "./components/shared/icon-picker";
|
|
64
83
|
export { Initials, initialsOf } from "./components/shared/initials";
|
|
65
84
|
export { ErrorState, type RouteError } from "./components/shared/layout/error-state";
|
|
66
85
|
export {
|
|
@@ -77,8 +96,10 @@ export { Notice, type NoticeTone } from "./components/shared/notice";
|
|
|
77
96
|
export { type DecimalLike, FormattedNumber } from "./components/shared/number/formatted-number";
|
|
78
97
|
export { PageHeader } from "./components/shared/page-header";
|
|
79
98
|
export { PageSkeleton } from "./components/shared/page-skeleton";
|
|
99
|
+
export { ProgressBar, type ProgressTone } from "./components/shared/progress-bar";
|
|
80
100
|
export { SecretReveal } from "./components/shared/secret-reveal";
|
|
81
101
|
export { SectionCard } from "./components/shared/section-card";
|
|
102
|
+
export { SelectionButton } from "./components/shared/selection-button";
|
|
82
103
|
export { Stat } from "./components/shared/stat";
|
|
83
104
|
export { StatusBadge, statusTone, type Tone } from "./components/shared/status-badge";
|
|
84
105
|
export { SwitcherChevron } from "./components/shared/switcher-chevron";
|