lucentia-ui 1.3.0 → 1.4.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/dist/components/Calendar/ArrowLeftIcon.d.ts +8 -0
- package/dist/components/Calendar/ArrowLeftIcon.js +5 -0
- package/dist/components/Calendar/ArrowRightIcon.d.ts +8 -0
- package/dist/components/Calendar/ArrowRightIcon.js +5 -0
- package/dist/components/Calendar/Calendar.d.ts +6 -0
- package/dist/components/Calendar/Calendar.js +48 -0
- package/dist/components/Calendar/Calendar.module.css +75 -0
- package/dist/components/Calendar/index.d.ts +2 -0
- package/dist/components/Calendar/index.js +1 -0
- package/dist/components/Calendar/types.d.ts +6 -0
- package/dist/components/Calendar/types.js +1 -0
- package/dist/components/Chart/BarChart/BarChart.js +0 -1
- package/dist/components/Chart/ChartTooltip.js +33 -10
- package/dist/components/DatePicker/CalendarIcon.d.ts +8 -0
- package/dist/components/DatePicker/CalendarIcon.js +5 -0
- package/dist/components/DatePicker/DatePicker.d.ts +2 -0
- package/dist/components/DatePicker/DatePicker.js +32 -0
- package/dist/components/DatePicker/DatePicker.module.css +52 -0
- package/dist/components/DatePicker/index.d.ts +2 -0
- package/dist/components/DatePicker/index.js +1 -0
- package/dist/components/DatePicker/types.d.ts +6 -0
- package/dist/components/DatePicker/types.js +1 -0
- package/dist/components/Feedback/Popover/Popover.d.ts +3 -0
- package/dist/components/Feedback/Popover/Popover.js +22 -0
- package/dist/components/Feedback/Popover/PopoverContent.d.ts +2 -0
- package/dist/components/Feedback/Popover/PopoverContent.js +62 -0
- package/dist/components/Feedback/Popover/PopoverTrigger.d.ts +2 -0
- package/dist/components/Feedback/Popover/PopoverTrigger.js +21 -0
- package/dist/components/Feedback/Popover/popover.module.css +14 -0
- package/dist/components/Feedback/Popover/types.d.ts +19 -0
- package/dist/components/Feedback/Popover/types.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const ArrowLeftIcon = ({ size = 24, color = "tranparent", className = "", }) => {
|
|
3
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M15.0303 16.9697C15.3232 17.2626 15.3232 17.7374 15.0303 18.0303C14.7374 18.3232 14.2626 18.3232 13.9697 18.0303L8.46972 12.5303C8.17683 12.2374 8.17683 11.7626 8.46972 11.4697L13.9697 5.96973C14.2626 5.67684 14.7374 5.67684 15.0303 5.96973C15.3232 6.26262 15.3232 6.73738 15.0303 7.03028L10.0605 12L15.0303 16.9697Z", fill: "currentColor" }) }) }));
|
|
4
|
+
};
|
|
5
|
+
export default ArrowLeftIcon;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
export const ArrowRightIcon = ({ size = 24, color = "tranparent", className = "", }) => {
|
|
3
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M8.96973 7.03027C8.67684 6.73738 8.67684 6.26261 8.96973 5.96972C9.26262 5.67683 9.73738 5.67683 10.0303 5.96972L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L10.0303 18.0303C9.73738 18.3232 9.26262 18.3232 8.96973 18.0303C8.67684 17.7374 8.67684 17.2626 8.96973 16.9697L13.9395 12L8.96973 7.03027Z", fill: "currentColor" }) }) }));
|
|
4
|
+
};
|
|
5
|
+
export default ArrowRightIcon;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CalendarProps } from "./types";
|
|
2
|
+
interface ExtendedCalendarProps extends CalendarProps {
|
|
3
|
+
locale?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const Calendar: ({ value, onChange, variant, locale, }: ExtendedCalendarProps) => import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { ArrowRightIcon } from "./ArrowRightIcon";
|
|
5
|
+
import { ArrowLeftIcon } from "./ArrowLeftIcon";
|
|
6
|
+
import { generateCalendar } from "../../utils/date/generateCalendar";
|
|
7
|
+
import styles from "./Calendar.module.css";
|
|
8
|
+
export const Calendar = ({ value, onChange, variant = "embedded", locale = "ja-JP", // デフォルト値を設定
|
|
9
|
+
}) => {
|
|
10
|
+
const [currentMonth, setCurrentMonth] = useState(value !== null && value !== void 0 ? value : new Date());
|
|
11
|
+
const days = generateCalendar(currentMonth);
|
|
12
|
+
// --- i18n Helpers ---
|
|
13
|
+
// 1. 年月の表示(例:2024年3月 / March 2024)
|
|
14
|
+
const formatTitle = (date) => {
|
|
15
|
+
return new Intl.DateTimeFormat(locale, {
|
|
16
|
+
year: "numeric",
|
|
17
|
+
month: "long",
|
|
18
|
+
}).format(date);
|
|
19
|
+
};
|
|
20
|
+
// 2. 曜日のリスト生成(例:日〜土 / Su〜Sa)
|
|
21
|
+
const getWeekDays = () => {
|
|
22
|
+
const baseDate = new Date(2021, 0, 3); // 日曜日から始まる任意の日付
|
|
23
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
24
|
+
const date = new Date(baseDate);
|
|
25
|
+
date.setDate(baseDate.getDate() + i);
|
|
26
|
+
return new Intl.DateTimeFormat(locale, { weekday: "short" }).format(date);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
// --- Logic ---
|
|
30
|
+
const isSameDay = (a, b) => a.toDateString() === b.toDateString();
|
|
31
|
+
const isToday = (date) => {
|
|
32
|
+
const today = new Date();
|
|
33
|
+
return date.toDateString() === today.toDateString();
|
|
34
|
+
};
|
|
35
|
+
const handleMonthChange = (offset) => {
|
|
36
|
+
setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + offset, 1));
|
|
37
|
+
};
|
|
38
|
+
return (_jsxs("div", { className: `${styles.root} ${styles[variant]}`, children: [_jsxs("div", { className: styles.header, children: [_jsx("button", { onClick: () => handleMonthChange(-1), children: _jsx(ArrowLeftIcon, {}) }), _jsx("span", { className: styles.title, children: formatTitle(currentMonth) }), _jsx("button", { onClick: () => handleMonthChange(1), children: _jsx(ArrowRightIcon, {}) })] }), _jsx("div", { className: styles.week, children: getWeekDays().map((d) => (_jsx("div", { className: styles.weekDay, children: d }, d))) }), _jsx("div", { className: styles.grid, children: days.map((day, i) => {
|
|
39
|
+
const isSelected = value && isSameDay(day.date, value);
|
|
40
|
+
const today = isToday(day.date);
|
|
41
|
+
return (_jsx("button", { onClick: () => onChange === null || onChange === void 0 ? void 0 : onChange(day.date), className: `
|
|
42
|
+
${styles.cell}
|
|
43
|
+
${!day.isCurrentMonth ? styles.outside : ""}
|
|
44
|
+
${isSelected ? styles.selected : ""}
|
|
45
|
+
${today ? styles.today : ""}
|
|
46
|
+
`, children: day.date.getDate() }, i));
|
|
47
|
+
}) })] }));
|
|
48
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
font-size: var(--font-size-14);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
/* ===== variant ===== */
|
|
6
|
+
|
|
7
|
+
.embedded {
|
|
8
|
+
padding: var(--space-lg);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.standalone {
|
|
12
|
+
padding: var(--space-lg);
|
|
13
|
+
border-radius: var(--radius-md);
|
|
14
|
+
box-shadow: var(--shadow-md);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* ===== layout ===== */
|
|
18
|
+
|
|
19
|
+
.header {
|
|
20
|
+
color: var(--color-on-surface);
|
|
21
|
+
display: flex;
|
|
22
|
+
justify-content: space-between;
|
|
23
|
+
align-items: center;
|
|
24
|
+
margin-bottom: var(--space-lg);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.title {
|
|
28
|
+
font-size: var(--font-size-16);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.week {
|
|
32
|
+
display: grid;
|
|
33
|
+
grid-template-columns: repeat(7, 1fr);
|
|
34
|
+
margin-bottom: var(--space-xs);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.weekDay {
|
|
38
|
+
text-align: center;
|
|
39
|
+
font-size: var(--font-size-14);
|
|
40
|
+
color: var(--color-on-surface-variant);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.grid {
|
|
44
|
+
display: grid;
|
|
45
|
+
grid-template-columns: repeat(7, 1fr);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ===== cell ===== */
|
|
49
|
+
|
|
50
|
+
.cell {
|
|
51
|
+
width: 40px;
|
|
52
|
+
height: 40px;
|
|
53
|
+
padding: 8px;
|
|
54
|
+
border-radius: var(--radius-max);
|
|
55
|
+
background: transparent;
|
|
56
|
+
font-weight: var(--font-weight-medium);
|
|
57
|
+
color: var(--color-on-surface);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.cell:not(.selected):hover {
|
|
61
|
+
background: var(--color-primary-container);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.outside {
|
|
65
|
+
color: var(--color-on-surface-variant);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.selected {
|
|
69
|
+
background: var(--color-primary);
|
|
70
|
+
color: var(--color-on-primary);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.today {
|
|
74
|
+
border: 1px solid var(--color-border);
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Calendar } from "./Calendar";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -18,6 +18,5 @@ export const BarChart = ({ data, keys, height = 300, barGap = 16 }) => {
|
|
|
18
18
|
y: 0,
|
|
19
19
|
});
|
|
20
20
|
const [tooltip, setTooltip] = useState(null);
|
|
21
|
-
// BarChart.tsx の return 部分を修正
|
|
22
21
|
return (_jsx("div", { style: { width: "100%" }, children: _jsxs(ChartContainer, { height: height, onPointerMove: (x, y) => setCursor({ x, y }), children: [_jsx(ChartGrid, {}), _jsx(ChartXAxis, { labels: labels }), _jsx(ChartYAxis, { ticks: ticks, max: ticks[ticks.length - 1] }), _jsx(BarSeries, { data: data, keys: seriesKeys, max: max, gap: barGap, onHover: (label, key, value) => setTooltip({ label, key, value }), onLeave: () => setTooltip(null) }), tooltip && (_jsxs(ChartTooltip, { x: cursor.x + 8, y: cursor.y + 8, children: [_jsx("div", { children: tooltip.label }), _jsxs("strong", { children: [tooltip.key, ": ", tooltip.value] })] }))] }) }));
|
|
23
22
|
};
|
|
@@ -1,12 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useChart } from "./ChartContext";
|
|
2
3
|
export const ChartTooltip = ({ x, y, children }) => {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
const { width, height } = useChart();
|
|
5
|
+
const tooltipWidth = 120;
|
|
6
|
+
const tooltipHeight = 64;
|
|
7
|
+
const offset = 10;
|
|
8
|
+
let tx = x + offset;
|
|
9
|
+
let ty = y - offset;
|
|
10
|
+
// 右はみ出し防止
|
|
11
|
+
if (tx + tooltipWidth > width) {
|
|
12
|
+
tx = x - tooltipWidth - offset;
|
|
13
|
+
}
|
|
14
|
+
// 下はみ出し防止
|
|
15
|
+
if (ty + tooltipHeight > height) {
|
|
16
|
+
ty = height - tooltipHeight;
|
|
17
|
+
}
|
|
18
|
+
// 上はみ出し防止
|
|
19
|
+
if (ty < 0) {
|
|
20
|
+
ty = offset;
|
|
21
|
+
}
|
|
22
|
+
return (_jsxs("foreignObject", { x: tx, y: ty, width: tooltipWidth, height: tooltipHeight, style: {
|
|
23
|
+
borderRadius: "var(--radius-sm)",
|
|
24
|
+
overflow: "visible",
|
|
25
|
+
}, children: [_jsxs("div", { style: {
|
|
26
|
+
background: "var(--color-surface)",
|
|
27
|
+
backdropFilter: "var(--blur)",
|
|
28
|
+
border: "1px solid var(--color-border)",
|
|
29
|
+
borderRadius: "var(--radius-sm)",
|
|
30
|
+
padding: "var(--space-md)",
|
|
31
|
+
fontSize: "var(--font-size-14)",
|
|
32
|
+
color: "var(--color-on-surface)",
|
|
33
|
+
whiteSpace: "nowrap",
|
|
34
|
+
}, children: [children, " "] }), " "] }));
|
|
12
35
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export const CalendarIcon = ({ size = 24, color = "tranparent", className = "", }) => {
|
|
3
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: className, children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M21 19C21 20.1046 20.1046 21 19 21H5C3.89543 21 3 20.1046 3 19V9H21V19ZM5.5 16C5.22386 16 5 16.2239 5 16.5V17.5C5 17.7761 5.22386 18 5.5 18H6.5C6.77614 18 7 17.7761 7 17.5V16.5C7 16.2239 6.77614 16 6.5 16H5.5ZM9.5 16C9.22386 16 9 16.2239 9 16.5V17.5C9 17.7761 9.22386 18 9.5 18H10.5C10.7761 18 11 17.7761 11 17.5V16.5C11 16.2239 10.7761 16 10.5 16H9.5ZM13.5 16C13.2239 16 13 16.2239 13 16.5V17.5C13 17.7761 13.2239 18 13.5 18H14.5C14.7761 18 15 17.7761 15 17.5V16.5C15 16.2239 14.7761 16 14.5 16H13.5ZM17.5 16C17.2239 16 17 16.2239 17 16.5V17.5C17 17.7761 17.2239 18 17.5 18H18.5C18.7761 18 19 17.7761 19 17.5V16.5C19 16.2239 18.7761 16 18.5 16H17.5ZM5.5 12C5.22386 12 5 12.2239 5 12.5V13.5C5 13.7761 5.22386 14 5.5 14H6.5C6.77614 14 7 13.7761 7 13.5V12.5C7 12.2239 6.77614 12 6.5 12H5.5ZM9.5 12C9.22386 12 9 12.2239 9 12.5V13.5C9 13.7761 9.22386 14 9.5 14H10.5C10.7761 14 11 13.7761 11 13.5V12.5C11 12.2239 10.7761 12 10.5 12H9.5ZM13.5 12C13.2239 12 13 12.2239 13 12.5V13.5C13 13.7761 13.2239 14 13.5 14H14.5C14.7761 14 15 13.7761 15 13.5V12.5C15 12.2239 14.7761 12 14.5 12H13.5ZM17.5 12C17.2239 12 17 12.2239 17 12.5V13.5C17 13.7761 17.2239 14 17.5 14H18.5C18.7761 14 19 13.7761 19 13.5V12.5C19 12.2239 18.7761 12 18.5 12H17.5Z", fill: "currentColor" }), _jsx("path", { d: "M7.5 3C7.77614 3 8 3.22386 8 3.5V5H16V3.5C16 3.22386 16.2239 3 16.5 3H17.5C17.7761 3 18 3.22386 18 3.5V5H19C20.1046 5 21 5.89543 21 7V8H3V7C3 5.89543 3.89543 5 5 5H6V3.5C6 3.22386 6.22386 3 6.5 3H7.5Z", fill: "currentColor" })] }) }));
|
|
4
|
+
};
|
|
5
|
+
export default CalendarIcon;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Popover } from "../Feedback/Popover/Popover";
|
|
5
|
+
import { PopoverTrigger } from "../Feedback/Popover/PopoverTrigger";
|
|
6
|
+
import { PopoverContent } from "../Feedback/Popover/PopoverContent";
|
|
7
|
+
import { Calendar } from "../Calendar/Calendar";
|
|
8
|
+
import { CalendarIcon } from "./CalendarIcon";
|
|
9
|
+
import styeles from "./DatePicker.module.css";
|
|
10
|
+
export const DatePicker = ({ value: valueProp, defaultValue, onChange, placeholder = "YYYY/MM/DD", }) => {
|
|
11
|
+
// --- value制御 ---
|
|
12
|
+
const isControlled = valueProp !== undefined;
|
|
13
|
+
const [internalValue, setInternalValue] = useState(defaultValue !== null && defaultValue !== void 0 ? defaultValue : null);
|
|
14
|
+
const value = isControlled ? valueProp : internalValue;
|
|
15
|
+
const setValue = (date) => {
|
|
16
|
+
if (!isControlled) {
|
|
17
|
+
setInternalValue(date);
|
|
18
|
+
}
|
|
19
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(date);
|
|
20
|
+
};
|
|
21
|
+
// --- Popover制御(追加) ---
|
|
22
|
+
const [open, setOpen] = useState(false);
|
|
23
|
+
const formatDate = (date) => {
|
|
24
|
+
if (!date)
|
|
25
|
+
return "";
|
|
26
|
+
return date.toLocaleDateString();
|
|
27
|
+
};
|
|
28
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className: styeles.inputWrapper, children: [_jsx("input", { readOnly: true, className: styeles.dateInput, value: formatDate(value), placeholder: placeholder }), _jsx(CalendarIcon, { className: styeles.calendarIcon })] }) }), _jsx(PopoverContent, { children: _jsx(Calendar, { value: value, onChange: (date) => {
|
|
29
|
+
setValue(date);
|
|
30
|
+
setOpen(false);
|
|
31
|
+
} }) })] }));
|
|
32
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
.inputWrapper {
|
|
3
|
+
position: relative;
|
|
4
|
+
width: 100%; /* 必要に応じて調整 */
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
.calendarIcon{
|
|
9
|
+
color: var(--color-on-surface-variant);
|
|
10
|
+
position: absolute;
|
|
11
|
+
top: 50%;
|
|
12
|
+
transform: translateY(-50%);
|
|
13
|
+
right: 16px;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dateInput{
|
|
18
|
+
font-family: var(--font);
|
|
19
|
+
border-radius: var(--radius-sm);
|
|
20
|
+
border: 2px solid var(--color-background);
|
|
21
|
+
outline: none;
|
|
22
|
+
background: var(--color-surface-container);
|
|
23
|
+
color: var(--color-on-surface);
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
transition:
|
|
26
|
+
border-color 0.2s ease,
|
|
27
|
+
box-shadow 0.2s ease;
|
|
28
|
+
|
|
29
|
+
font-size: var(--font-size-16);
|
|
30
|
+
padding: var(--space-md) var(--space-lg);
|
|
31
|
+
box-shadow: var(--shadow-md-in);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
/* ===== Focus ===== */
|
|
37
|
+
.dateInput:focus {
|
|
38
|
+
outline: none;
|
|
39
|
+
border: 2px solid var(--color-primary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ===== Error ===== */
|
|
43
|
+
.error {
|
|
44
|
+
border: 2px solid var(--color-error);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* ===== Disabled ===== */
|
|
48
|
+
.dateInput:disabled {
|
|
49
|
+
opacity: 0.5;
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
}
|
|
52
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DatePicker } from "./DatePicker";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { PopoverProps, PopoverContextType } from "./types";
|
|
2
|
+
export declare const PopoverContext: import("react").Context<PopoverContextType | null>;
|
|
3
|
+
export declare const Popover: ({ children, open: openProp, defaultOpen, onOpenChange, }: PopoverProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useRef, useState } from "react";
|
|
4
|
+
import styles from "./popover.module.css";
|
|
5
|
+
export const PopoverContext = createContext(null);
|
|
6
|
+
export const Popover = ({ children, open: openProp, defaultOpen = false, onOpenChange, }) => {
|
|
7
|
+
const isControlled = openProp !== undefined;
|
|
8
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
9
|
+
const open = isControlled ? openProp : internalOpen;
|
|
10
|
+
const setOpen = (next) => {
|
|
11
|
+
if (!isControlled) {
|
|
12
|
+
setInternalOpen(next);
|
|
13
|
+
}
|
|
14
|
+
onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
|
|
15
|
+
};
|
|
16
|
+
const referenceRef = useRef(null);
|
|
17
|
+
return (_jsx(PopoverContext.Provider, { value: {
|
|
18
|
+
open,
|
|
19
|
+
setOpen,
|
|
20
|
+
referenceRef,
|
|
21
|
+
}, children: _jsx("div", { className: styles.root, children: children }) }));
|
|
22
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useContext, useEffect, useState } from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
5
|
+
import { PopoverContext } from "./Popover";
|
|
6
|
+
import styles from "./popover.module.css";
|
|
7
|
+
import { useFloating, offset, flip, shift, autoUpdate, } from "@floating-ui/react";
|
|
8
|
+
export const PopoverContent = ({ children }) => {
|
|
9
|
+
const context = useContext(PopoverContext);
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error("PopoverContent must be used within Popover");
|
|
12
|
+
}
|
|
13
|
+
const { open, setOpen, referenceRef } = context;
|
|
14
|
+
const [mounted, setMounted] = useState(false);
|
|
15
|
+
// SSR対策(Next.js)
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
setMounted(true);
|
|
18
|
+
}, []);
|
|
19
|
+
const { x, y, strategy, refs } = useFloating({
|
|
20
|
+
placement: "bottom-start",
|
|
21
|
+
middleware: [offset(8), flip(), shift()],
|
|
22
|
+
whileElementsMounted: autoUpdate,
|
|
23
|
+
});
|
|
24
|
+
// reference接続
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (referenceRef.current) {
|
|
27
|
+
refs.setReference(referenceRef.current);
|
|
28
|
+
}
|
|
29
|
+
}, [referenceRef, refs]);
|
|
30
|
+
// outside click + Escape
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const handleClickOutside = (event) => {
|
|
33
|
+
const target = event.target;
|
|
34
|
+
if (refs.floating.current &&
|
|
35
|
+
!refs.floating.current.contains(target) &&
|
|
36
|
+
referenceRef.current &&
|
|
37
|
+
!referenceRef.current.contains(target)) {
|
|
38
|
+
setOpen(false);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const handleKeyDown = (event) => {
|
|
42
|
+
if (event.key === "Escape") {
|
|
43
|
+
setOpen(false);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
if (open) {
|
|
47
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
48
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
49
|
+
}
|
|
50
|
+
return () => {
|
|
51
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
52
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
53
|
+
};
|
|
54
|
+
}, [open, setOpen, refs, referenceRef]);
|
|
55
|
+
if (!open || !mounted)
|
|
56
|
+
return null;
|
|
57
|
+
return createPortal(_jsx("div", { ref: refs.setFloating, className: styles.content, style: {
|
|
58
|
+
position: strategy,
|
|
59
|
+
top: y !== null && y !== void 0 ? y : 0,
|
|
60
|
+
left: x !== null && x !== void 0 ? x : 0,
|
|
61
|
+
}, children: children }), document.body);
|
|
62
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cloneElement, useContext } from "react";
|
|
4
|
+
import { PopoverContext } from "./Popover";
|
|
5
|
+
export const PopoverTrigger = ({ children, asChild }) => {
|
|
6
|
+
const context = useContext(PopoverContext);
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw new Error("PopoverTrigger must be used within Popover");
|
|
9
|
+
}
|
|
10
|
+
const { open, setOpen, referenceRef } = context;
|
|
11
|
+
const handleClick = () => {
|
|
12
|
+
setOpen(!open);
|
|
13
|
+
};
|
|
14
|
+
if (asChild) {
|
|
15
|
+
return cloneElement(children, {
|
|
16
|
+
ref: referenceRef,
|
|
17
|
+
onClick: handleClick,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return (_jsx("button", { ref: referenceRef, onClick: handleClick, children: children }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ReactNode, ReactElement } from "react";
|
|
2
|
+
export type PopoverProps = {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
open?: boolean;
|
|
5
|
+
onOpenChange?: (open: boolean) => void;
|
|
6
|
+
defaultOpen?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type PopoverContextType = {
|
|
9
|
+
open: boolean;
|
|
10
|
+
setOpen: (open: boolean) => void;
|
|
11
|
+
referenceRef: React.RefObject<HTMLElement | null>;
|
|
12
|
+
};
|
|
13
|
+
export type PopoverTriggerProps = {
|
|
14
|
+
children: ReactElement;
|
|
15
|
+
asChild?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type PopoverContentProps = {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,5 +12,7 @@ export * from "./components/Typography";
|
|
|
12
12
|
export * from "./components/Select";
|
|
13
13
|
export * from "./components/Switch";
|
|
14
14
|
export * from "./components/Feedback/Modal";
|
|
15
|
+
export * from "./components/DatePicker";
|
|
16
|
+
export * from "./components/Calendar";
|
|
15
17
|
export * from "./components/Chart";
|
|
16
18
|
export * from "./components/Extra/Clock";
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,8 @@ export * from "./components/Typography";
|
|
|
13
13
|
export * from "./components/Select";
|
|
14
14
|
export * from "./components/Switch";
|
|
15
15
|
export * from "./components/Feedback/Modal";
|
|
16
|
+
export * from "./components/DatePicker";
|
|
17
|
+
export * from "./components/Calendar";
|
|
16
18
|
/* ===== Chart ===== */
|
|
17
19
|
export * from "./components/Chart";
|
|
18
20
|
/* ===== Extra ===== */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lucentia-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "React UI design token and component system based on neumorphism, featuring two color themes: light and dark.",
|
|
5
5
|
"homepage": "https://lucentia.rikiyamatsuda.com/en",
|
|
6
6
|
"main": "dist/index.js",
|