@kjaniec-dev/ui 0.2.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/README.md +89 -0
- package/dist/index.cjs +976 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +281 -0
- package/dist/index.d.ts +281 -0
- package/dist/index.js +895 -0
- package/dist/index.js.map +1 -0
- package/dist/ui.css +26 -0
- package/package.json +71 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,976 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clsx = require('clsx');
|
|
4
|
+
var tailwindMerge = require('tailwind-merge');
|
|
5
|
+
var React16 = require('react');
|
|
6
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var React16__namespace = /*#__PURE__*/_interopNamespace(React16);
|
|
28
|
+
|
|
29
|
+
// src/lib/cn.ts
|
|
30
|
+
function cn(...inputs) {
|
|
31
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
32
|
+
}
|
|
33
|
+
var buttonVariants = classVarianceAuthority.cva(
|
|
34
|
+
[
|
|
35
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap select-none",
|
|
36
|
+
"font-sans font-semibold leading-none",
|
|
37
|
+
"border border-transparent rounded-kj-md cursor-pointer",
|
|
38
|
+
"transition-[background-color,color,border-color,box-shadow,transform] duration-150",
|
|
39
|
+
"active:translate-y-px",
|
|
40
|
+
"focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-ring/45",
|
|
41
|
+
"disabled:opacity-50 disabled:pointer-events-none"
|
|
42
|
+
],
|
|
43
|
+
{
|
|
44
|
+
variants: {
|
|
45
|
+
variant: {
|
|
46
|
+
primary: "bg-primary text-primary-foreground hover:bg-primary-hover",
|
|
47
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover",
|
|
48
|
+
outline: "bg-transparent text-foreground border-border hover:bg-muted hover:border-muted-foreground",
|
|
49
|
+
ghost: "bg-transparent text-foreground hover:bg-muted",
|
|
50
|
+
danger: "bg-danger text-white hover:brightness-95"
|
|
51
|
+
},
|
|
52
|
+
size: {
|
|
53
|
+
sm: "h-8 px-3 text-[0.8rem] rounded-kj-sm",
|
|
54
|
+
md: "h-10 px-[1.1rem] text-sm",
|
|
55
|
+
lg: "h-12 px-6 text-base",
|
|
56
|
+
icon: "h-10 w-10 p-0",
|
|
57
|
+
"icon-sm": "h-8 w-8 p-0 rounded-kj-sm"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
defaultVariants: { variant: "primary", size: "md" }
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
var Button = React16__namespace.forwardRef(
|
|
64
|
+
({ className, variant, size, loading, leadingIcon, trailingIcon, children, disabled, ...props }, ref) => {
|
|
65
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
66
|
+
"button",
|
|
67
|
+
{
|
|
68
|
+
ref,
|
|
69
|
+
className: cn(buttonVariants({ variant, size }), loading && "relative", className),
|
|
70
|
+
disabled: disabled || loading,
|
|
71
|
+
"aria-busy": loading || void 0,
|
|
72
|
+
...props,
|
|
73
|
+
children: [
|
|
74
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
75
|
+
"span",
|
|
76
|
+
{
|
|
77
|
+
"aria-hidden": true,
|
|
78
|
+
className: "absolute h-[1em] w-[1em] rounded-full border-2 border-current border-t-transparent animate-spin"
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("contents", loading && "invisible"), children: [
|
|
82
|
+
leadingIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "[&_svg]:h-[1.05em] [&_svg]:w-[1.05em]", children: leadingIcon }),
|
|
83
|
+
children,
|
|
84
|
+
trailingIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "[&_svg]:h-[1.05em] [&_svg]:w-[1.05em]", children: trailingIcon })
|
|
85
|
+
] })
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
Button.displayName = "Button";
|
|
92
|
+
var badgeVariants = classVarianceAuthority.cva(
|
|
93
|
+
"inline-flex items-center gap-1.5 px-2.5 py-0.5 text-xs font-semibold leading-snug rounded-full border border-transparent",
|
|
94
|
+
{
|
|
95
|
+
variants: {
|
|
96
|
+
variant: {
|
|
97
|
+
neutral: "bg-muted text-muted-foreground",
|
|
98
|
+
primary: "bg-primary/15 text-primary-hover dark:text-primary",
|
|
99
|
+
success: "bg-success-surface text-success",
|
|
100
|
+
warning: "bg-warning-surface text-warning",
|
|
101
|
+
danger: "bg-danger-surface text-danger",
|
|
102
|
+
info: "bg-info-surface text-info",
|
|
103
|
+
solid: "bg-primary text-primary-foreground"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
defaultVariants: { variant: "neutral" }
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
var Badge = React16__namespace.forwardRef(
|
|
110
|
+
({ className, variant, dot, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className: cn(badgeVariants({ variant }), className), ...props, children: [
|
|
111
|
+
dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-current", "aria-hidden": true }),
|
|
112
|
+
children
|
|
113
|
+
] })
|
|
114
|
+
);
|
|
115
|
+
Badge.displayName = "Badge";
|
|
116
|
+
var alertVariants = classVarianceAuthority.cva(
|
|
117
|
+
"flex gap-3 items-start p-[0.9rem_1.1rem] rounded-kj-md border text-sm",
|
|
118
|
+
{
|
|
119
|
+
variants: {
|
|
120
|
+
variant: {
|
|
121
|
+
info: "bg-info-surface border-info/30",
|
|
122
|
+
success: "bg-success-surface border-success/30",
|
|
123
|
+
warning: "bg-warning-surface border-warning/30",
|
|
124
|
+
danger: "bg-danger-surface border-danger/30"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
defaultVariants: { variant: "info" }
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
var iconColor = {
|
|
131
|
+
info: "text-info",
|
|
132
|
+
success: "text-success",
|
|
133
|
+
warning: "text-warning",
|
|
134
|
+
danger: "text-danger"
|
|
135
|
+
};
|
|
136
|
+
var Alert = React16__namespace.forwardRef(
|
|
137
|
+
({ className, variant = "info", icon, title, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props, children: [
|
|
138
|
+
icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("shrink-0 mt-0.5 [&_svg]:h-[1.15rem] [&_svg]:w-[1.15rem]", iconColor[variant ?? "info"]), children: icon }),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground", children: [
|
|
140
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-bold m-0 mb-0.5 text-sm", children: title }),
|
|
141
|
+
children && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 opacity-85", children })
|
|
142
|
+
] })
|
|
143
|
+
] })
|
|
144
|
+
);
|
|
145
|
+
Alert.displayName = "Alert";
|
|
146
|
+
var Spinner = React16__namespace.forwardRef(
|
|
147
|
+
({ className, size = 24, style, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
148
|
+
"span",
|
|
149
|
+
{
|
|
150
|
+
ref,
|
|
151
|
+
role: "status",
|
|
152
|
+
"aria-label": "Loading",
|
|
153
|
+
className: cn(
|
|
154
|
+
"inline-block rounded-full border-[2.5px] border-muted border-t-primary animate-spin align-middle",
|
|
155
|
+
className
|
|
156
|
+
),
|
|
157
|
+
style: { width: size, height: size, ...style },
|
|
158
|
+
...props
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
Spinner.displayName = "Spinner";
|
|
163
|
+
var Progress = React16__namespace.forwardRef(
|
|
164
|
+
({ className, value = 0, tone = "primary", ...props }, ref) => {
|
|
165
|
+
const pct = Math.max(0, Math.min(100, value));
|
|
166
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
167
|
+
"div",
|
|
168
|
+
{
|
|
169
|
+
ref,
|
|
170
|
+
role: "progressbar",
|
|
171
|
+
"aria-valuenow": pct,
|
|
172
|
+
"aria-valuemin": 0,
|
|
173
|
+
"aria-valuemax": 100,
|
|
174
|
+
className: cn("h-2 w-full overflow-hidden rounded-full bg-muted", className),
|
|
175
|
+
...props,
|
|
176
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
177
|
+
"span",
|
|
178
|
+
{
|
|
179
|
+
className: cn(
|
|
180
|
+
"block h-full rounded-full transition-[width] duration-500 ease-out",
|
|
181
|
+
tone === "secondary" ? "bg-secondary" : "bg-primary"
|
|
182
|
+
),
|
|
183
|
+
style: { width: `${pct}%` }
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
Progress.displayName = "Progress";
|
|
191
|
+
var baseField = "w-full font-sans text-sm text-foreground bg-surface border rounded-kj-md px-[0.85rem] transition-[border-color,box-shadow] duration-150 placeholder:text-muted-foreground focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30 disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed";
|
|
192
|
+
var Input = React16__namespace.forwardRef(
|
|
193
|
+
({ className, error, leadingIcon, style, ...props }, ref) => {
|
|
194
|
+
const field = /* @__PURE__ */ jsxRuntime.jsx(
|
|
195
|
+
"input",
|
|
196
|
+
{
|
|
197
|
+
ref,
|
|
198
|
+
"aria-invalid": error || void 0,
|
|
199
|
+
className: cn(
|
|
200
|
+
baseField,
|
|
201
|
+
"py-[calc(0.6rem*var(--kj-density,1))]",
|
|
202
|
+
error ? "border-danger focus:border-danger focus:ring-danger/25" : "border-input",
|
|
203
|
+
leadingIcon && "pl-[2.3rem]",
|
|
204
|
+
className
|
|
205
|
+
),
|
|
206
|
+
...props
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
if (!leadingIcon) return field;
|
|
210
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative flex items-center", children: [
|
|
211
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-[0.8rem] text-muted-foreground [&_svg]:h-[1.05rem] [&_svg]:w-[1.05rem] pointer-events-none", children: leadingIcon }),
|
|
212
|
+
field
|
|
213
|
+
] });
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
Input.displayName = "Input";
|
|
217
|
+
var Textarea = React16__namespace.forwardRef(
|
|
218
|
+
({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
219
|
+
"textarea",
|
|
220
|
+
{
|
|
221
|
+
ref,
|
|
222
|
+
"aria-invalid": error || void 0,
|
|
223
|
+
className: cn(
|
|
224
|
+
baseField,
|
|
225
|
+
"py-[calc(0.6rem*var(--kj-density,1))] min-h-[84px] leading-relaxed resize-y",
|
|
226
|
+
error ? "border-danger focus:border-danger focus:ring-danger/25" : "border-input",
|
|
227
|
+
className
|
|
228
|
+
),
|
|
229
|
+
...props
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
);
|
|
233
|
+
Textarea.displayName = "Textarea";
|
|
234
|
+
var Label = React16__namespace.forwardRef(
|
|
235
|
+
({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs("label", { ref, className: cn("text-[0.8rem] font-semibold text-foreground", className), ...props, children: [
|
|
236
|
+
children,
|
|
237
|
+
required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-danger", children: " *" })
|
|
238
|
+
] })
|
|
239
|
+
);
|
|
240
|
+
Label.displayName = "Label";
|
|
241
|
+
var Hint = React16__namespace.forwardRef(
|
|
242
|
+
({ className, error, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
243
|
+
"span",
|
|
244
|
+
{
|
|
245
|
+
ref,
|
|
246
|
+
className: cn("text-[0.76rem]", error ? "text-danger" : "text-muted-foreground", className),
|
|
247
|
+
...props
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
);
|
|
251
|
+
Hint.displayName = "Hint";
|
|
252
|
+
var Field = React16__namespace.forwardRef(
|
|
253
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5", className), ...props })
|
|
254
|
+
);
|
|
255
|
+
Field.displayName = "Field";
|
|
256
|
+
var chevron = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E";
|
|
257
|
+
var Select = React16__namespace.forwardRef(
|
|
258
|
+
({ className, error, style, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
259
|
+
"select",
|
|
260
|
+
{
|
|
261
|
+
ref,
|
|
262
|
+
"aria-invalid": error || void 0,
|
|
263
|
+
className: cn(
|
|
264
|
+
"w-full appearance-none cursor-pointer font-sans text-sm text-foreground bg-surface",
|
|
265
|
+
"border rounded-kj-md py-[calc(0.6rem*var(--kj-density,1))] pl-[0.85rem] pr-9",
|
|
266
|
+
"transition-[border-color,box-shadow] duration-150",
|
|
267
|
+
"focus:outline-none focus:border-ring focus:ring-[3px] focus:ring-ring/30",
|
|
268
|
+
"disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed",
|
|
269
|
+
error ? "border-danger" : "border-input",
|
|
270
|
+
className
|
|
271
|
+
),
|
|
272
|
+
style: {
|
|
273
|
+
backgroundImage: `url("${chevron}")`,
|
|
274
|
+
backgroundRepeat: "no-repeat",
|
|
275
|
+
backgroundPosition: "right 0.75rem center",
|
|
276
|
+
backgroundSize: "1rem",
|
|
277
|
+
...style
|
|
278
|
+
},
|
|
279
|
+
...props,
|
|
280
|
+
children
|
|
281
|
+
}
|
|
282
|
+
)
|
|
283
|
+
);
|
|
284
|
+
Select.displayName = "Select";
|
|
285
|
+
var Checkbox = React16__namespace.forwardRef(
|
|
286
|
+
({ className, label, id, ...props }, ref) => {
|
|
287
|
+
const autoId = React16__namespace.useId();
|
|
288
|
+
const inputId = id ?? autoId;
|
|
289
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
290
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", className: "peer sr-only", ...props }),
|
|
291
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "grid place-items-center h-[1.15rem] w-[1.15rem] shrink-0 rounded-[0.4rem] border-[1.5px] border-input bg-surface transition-all duration-150 peer-checked:bg-primary peer-checked:border-primary peer-focus-visible:ring-[3px] peer-focus-visible:ring-ring/35 peer-checked:[&_svg]:opacity-100 peer-checked:[&_svg]:scale-100", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", className: "h-3 w-3 text-primary-foreground opacity-0 scale-50 transition-all duration-150", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }) }),
|
|
292
|
+
label
|
|
293
|
+
] });
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
Checkbox.displayName = "Checkbox";
|
|
297
|
+
var Radio = React16__namespace.forwardRef(
|
|
298
|
+
({ className, label, id, ...props }, ref) => {
|
|
299
|
+
const autoId = React16__namespace.useId();
|
|
300
|
+
const inputId = id ?? autoId;
|
|
301
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
302
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "radio", className: "peer sr-only", ...props }),
|
|
303
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "grid place-items-center h-[1.15rem] w-[1.15rem] shrink-0 rounded-full border-[1.5px] border-input bg-surface transition-all duration-150 peer-checked:bg-primary peer-checked:border-primary peer-focus-visible:ring-[3px] peer-focus-visible:ring-ring/35 peer-checked:[&>span]:opacity-100 peer-checked:[&>span]:scale-100", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-primary-foreground opacity-0 scale-[0.4] transition-all duration-150" }) }),
|
|
304
|
+
label
|
|
305
|
+
] });
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
Radio.displayName = "Radio";
|
|
309
|
+
var Switch = React16__namespace.forwardRef(
|
|
310
|
+
({ className, label, id, ...props }, ref) => {
|
|
311
|
+
const autoId = React16__namespace.useId();
|
|
312
|
+
const inputId = id ?? autoId;
|
|
313
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: inputId, className: cn("inline-flex items-center gap-2.5 cursor-pointer text-sm select-none", className), children: [
|
|
314
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { ref, id: inputId, type: "checkbox", role: "switch", className: "peer sr-only", ...props }),
|
|
315
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative h-[1.45rem] w-[2.6rem] shrink-0 rounded-full bg-input transition-colors duration-200 peer-checked:bg-primary peer-focus-visible:ring-[3px] peer-focus-visible:ring-ring/35 after:content-[''] after:absolute after:top-0.5 after:left-0.5 after:h-[calc(1.45rem-4px)] after:w-[calc(1.45rem-4px)] after:rounded-full after:bg-white after:shadow-kj-sm after:transition-transform after:duration-200 peer-checked:after:translate-x-[1.15rem]" }),
|
|
316
|
+
label
|
|
317
|
+
] });
|
|
318
|
+
}
|
|
319
|
+
);
|
|
320
|
+
Switch.displayName = "Switch";
|
|
321
|
+
var Slider = React16__namespace.forwardRef(
|
|
322
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
323
|
+
"input",
|
|
324
|
+
{
|
|
325
|
+
ref,
|
|
326
|
+
type: "range",
|
|
327
|
+
className: cn(
|
|
328
|
+
"kj-slider w-full h-1.5 rounded-full bg-input appearance-none cursor-pointer",
|
|
329
|
+
className
|
|
330
|
+
),
|
|
331
|
+
...props
|
|
332
|
+
}
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
Slider.displayName = "Slider";
|
|
336
|
+
var sliderThumbCSS = `
|
|
337
|
+
.kj-slider::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:9999px;background:var(--kj-primary);border:3px solid var(--kj-surface);box-shadow:var(--kj-shadow-sm);cursor:pointer}
|
|
338
|
+
.kj-slider::-moz-range-thumb{width:18px;height:18px;border-radius:9999px;background:var(--kj-primary);border:3px solid var(--kj-surface);box-shadow:var(--kj-shadow-sm);cursor:pointer}
|
|
339
|
+
`;
|
|
340
|
+
function Segmented({
|
|
341
|
+
options,
|
|
342
|
+
value,
|
|
343
|
+
onChange,
|
|
344
|
+
className,
|
|
345
|
+
...props
|
|
346
|
+
}) {
|
|
347
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
348
|
+
"div",
|
|
349
|
+
{
|
|
350
|
+
role: "tablist",
|
|
351
|
+
className: cn("inline-flex gap-0.5 p-[3px] rounded-kj-md bg-muted", className),
|
|
352
|
+
...props,
|
|
353
|
+
children: options.map((opt) => {
|
|
354
|
+
const active = opt.value === value;
|
|
355
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
356
|
+
"button",
|
|
357
|
+
{
|
|
358
|
+
type: "button",
|
|
359
|
+
role: "tab",
|
|
360
|
+
"aria-selected": active,
|
|
361
|
+
onClick: () => onChange(opt.value),
|
|
362
|
+
className: cn(
|
|
363
|
+
"px-3.5 py-1.5 text-[0.82rem] font-semibold rounded-[calc(var(--kj-radius-md)-3px)] cursor-pointer transition-all duration-150",
|
|
364
|
+
active ? "bg-surface text-foreground shadow-kj-xs" : "bg-transparent text-muted-foreground hover:text-foreground"
|
|
365
|
+
),
|
|
366
|
+
children: opt.label
|
|
367
|
+
},
|
|
368
|
+
opt.value
|
|
369
|
+
);
|
|
370
|
+
})
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
var Card = React16__namespace.forwardRef(
|
|
375
|
+
({ className, elevated, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
376
|
+
"div",
|
|
377
|
+
{
|
|
378
|
+
ref,
|
|
379
|
+
className: cn(
|
|
380
|
+
"bg-card text-card-foreground rounded-kj-xl overflow-hidden border",
|
|
381
|
+
elevated ? "border-transparent shadow-kj-lg" : "border-border shadow-kj-sm",
|
|
382
|
+
className
|
|
383
|
+
),
|
|
384
|
+
...props
|
|
385
|
+
}
|
|
386
|
+
)
|
|
387
|
+
);
|
|
388
|
+
Card.displayName = "Card";
|
|
389
|
+
var CardHeader = React16__namespace.forwardRef(
|
|
390
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("p-[1.35rem] flex flex-col gap-1", className), ...props })
|
|
391
|
+
);
|
|
392
|
+
CardHeader.displayName = "CardHeader";
|
|
393
|
+
var CardTitle = React16__namespace.forwardRef(
|
|
394
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("m-0 text-base font-bold tracking-[-0.01em]", className), ...props })
|
|
395
|
+
);
|
|
396
|
+
CardTitle.displayName = "CardTitle";
|
|
397
|
+
var CardDescription = React16__namespace.forwardRef(
|
|
398
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("m-0 text-[0.85rem] text-muted-foreground", className), ...props })
|
|
399
|
+
);
|
|
400
|
+
CardDescription.displayName = "CardDescription";
|
|
401
|
+
var CardContent = React16__namespace.forwardRef(
|
|
402
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("px-[1.35rem] pb-[1.35rem]", className), ...props })
|
|
403
|
+
);
|
|
404
|
+
CardContent.displayName = "CardContent";
|
|
405
|
+
var CardFooter = React16__namespace.forwardRef(
|
|
406
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
407
|
+
"div",
|
|
408
|
+
{
|
|
409
|
+
ref,
|
|
410
|
+
className: cn("flex gap-2.5 px-[1.35rem] py-[1.1rem] border-t border-border bg-muted/40", className),
|
|
411
|
+
...props
|
|
412
|
+
}
|
|
413
|
+
)
|
|
414
|
+
);
|
|
415
|
+
CardFooter.displayName = "CardFooter";
|
|
416
|
+
var Stat = React16__namespace.forwardRef(
|
|
417
|
+
({ className, label, value, delta, trend, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(Card, { ref, className: cn("p-[1.35rem] flex flex-col gap-2", className), ...props, children: [
|
|
418
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.78rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: label }),
|
|
419
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[2rem] font-bold tracking-[-0.03em] tabular-nums leading-none", children: value }),
|
|
420
|
+
delta && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
421
|
+
"span",
|
|
422
|
+
{
|
|
423
|
+
className: cn(
|
|
424
|
+
"inline-flex items-center gap-1 text-[0.8rem] font-semibold",
|
|
425
|
+
trend === "down" ? "text-danger" : "text-success"
|
|
426
|
+
),
|
|
427
|
+
children: [
|
|
428
|
+
trend === "down" ? "\u25BC" : "\u25B2",
|
|
429
|
+
" ",
|
|
430
|
+
delta
|
|
431
|
+
]
|
|
432
|
+
}
|
|
433
|
+
)
|
|
434
|
+
] })
|
|
435
|
+
);
|
|
436
|
+
Stat.displayName = "Stat";
|
|
437
|
+
var avatarVariants = classVarianceAuthority.cva(
|
|
438
|
+
"grid place-items-center shrink-0 rounded-full font-semibold border-2 border-surface",
|
|
439
|
+
{
|
|
440
|
+
variants: {
|
|
441
|
+
size: {
|
|
442
|
+
sm: "h-7 w-7 text-[0.7rem]",
|
|
443
|
+
md: "h-9 w-9 text-[0.8rem]",
|
|
444
|
+
lg: "h-12 w-12 text-base"
|
|
445
|
+
},
|
|
446
|
+
tone: {
|
|
447
|
+
secondary: "bg-secondary text-secondary-foreground",
|
|
448
|
+
primary: "bg-primary text-primary-foreground",
|
|
449
|
+
info: "bg-info text-white",
|
|
450
|
+
muted: "bg-muted text-muted-foreground"
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
defaultVariants: { size: "md", tone: "secondary" }
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
var Avatar = React16__namespace.forwardRef(
|
|
457
|
+
({ className, size, tone, src, alt, status, children, ...props }, ref) => {
|
|
458
|
+
const node = /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(avatarVariants({ size, tone }), "overflow-hidden", className), ...props, children: src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt, className: "h-full w-full object-cover" }) : children });
|
|
459
|
+
if (!status) return node;
|
|
460
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative inline-flex", children: [
|
|
461
|
+
node,
|
|
462
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute -right-px -bottom-px h-[0.7rem] w-[0.7rem] rounded-full bg-success border-2 border-surface" })
|
|
463
|
+
] });
|
|
464
|
+
}
|
|
465
|
+
);
|
|
466
|
+
Avatar.displayName = "Avatar";
|
|
467
|
+
var AvatarGroup = React16__namespace.forwardRef(
|
|
468
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex [&>*:not(:first-child)]:-ml-2.5", className), ...props })
|
|
469
|
+
);
|
|
470
|
+
AvatarGroup.displayName = "AvatarGroup";
|
|
471
|
+
var TabsContext = React16__namespace.createContext(null);
|
|
472
|
+
function useTabs() {
|
|
473
|
+
const ctx = React16__namespace.useContext(TabsContext);
|
|
474
|
+
if (!ctx) throw new Error("Tabs.* must be used within <Tabs>");
|
|
475
|
+
return ctx;
|
|
476
|
+
}
|
|
477
|
+
function Tabs({ value, defaultValue, onValueChange, className, children, ...props }) {
|
|
478
|
+
const [internal, setInternal] = React16__namespace.useState(defaultValue ?? "");
|
|
479
|
+
const current = value ?? internal;
|
|
480
|
+
const setValue = React16__namespace.useCallback(
|
|
481
|
+
(v) => {
|
|
482
|
+
if (value === void 0) setInternal(v);
|
|
483
|
+
onValueChange?.(v);
|
|
484
|
+
},
|
|
485
|
+
[value, onValueChange]
|
|
486
|
+
);
|
|
487
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, ...props, children }) });
|
|
488
|
+
}
|
|
489
|
+
var TabsList = React16__namespace.forwardRef(
|
|
490
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, role: "tablist", className: cn("flex gap-1 border-b border-border", className), ...props })
|
|
491
|
+
);
|
|
492
|
+
TabsList.displayName = "TabsList";
|
|
493
|
+
var TabsTrigger = React16__namespace.forwardRef(
|
|
494
|
+
({ className, value, children, ...props }, ref) => {
|
|
495
|
+
const { value: current, setValue } = useTabs();
|
|
496
|
+
const active = current === value;
|
|
497
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
498
|
+
"button",
|
|
499
|
+
{
|
|
500
|
+
ref,
|
|
501
|
+
type: "button",
|
|
502
|
+
role: "tab",
|
|
503
|
+
"aria-selected": active,
|
|
504
|
+
onClick: () => setValue(value),
|
|
505
|
+
className: cn(
|
|
506
|
+
"relative px-[0.9rem] py-2.5 text-sm font-semibold cursor-pointer transition-colors duration-150",
|
|
507
|
+
"after:content-[''] after:absolute after:left-[0.9rem] after:right-[0.9rem] after:-bottom-px after:h-0.5 after:rounded-sm after:transition-colors",
|
|
508
|
+
active ? "text-foreground after:bg-primary" : "text-muted-foreground hover:text-foreground after:bg-transparent",
|
|
509
|
+
className
|
|
510
|
+
),
|
|
511
|
+
...props,
|
|
512
|
+
children
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
TabsTrigger.displayName = "TabsTrigger";
|
|
518
|
+
var TabsContent = React16__namespace.forwardRef(
|
|
519
|
+
({ className, value, ...props }, ref) => {
|
|
520
|
+
const { value: current } = useTabs();
|
|
521
|
+
if (current !== value) return null;
|
|
522
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, role: "tabpanel", className: cn("pt-5 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
523
|
+
}
|
|
524
|
+
);
|
|
525
|
+
TabsContent.displayName = "TabsContent";
|
|
526
|
+
var AccordionContext = React16__namespace.createContext(null);
|
|
527
|
+
function Accordion({ type = "single", defaultValue = [], className, children, ...props }) {
|
|
528
|
+
const [open, setOpen] = React16__namespace.useState(defaultValue);
|
|
529
|
+
const toggle = React16__namespace.useCallback(
|
|
530
|
+
(v) => {
|
|
531
|
+
setOpen((prev) => {
|
|
532
|
+
const isOpen = prev.includes(v);
|
|
533
|
+
if (type === "single") return isOpen ? [] : [v];
|
|
534
|
+
return isOpen ? prev.filter((x) => x !== v) : [...prev, v];
|
|
535
|
+
});
|
|
536
|
+
},
|
|
537
|
+
[type]
|
|
538
|
+
);
|
|
539
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AccordionContext.Provider, { value: { open, toggle }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props, children }) });
|
|
540
|
+
}
|
|
541
|
+
var ItemContext = React16__namespace.createContext("");
|
|
542
|
+
var AccordionItem = React16__namespace.forwardRef(
|
|
543
|
+
({ className, value, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(ItemContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border-t border-border first:border-t-0", className), ...props }) })
|
|
544
|
+
);
|
|
545
|
+
AccordionItem.displayName = "AccordionItem";
|
|
546
|
+
var AccordionTrigger = React16__namespace.forwardRef(
|
|
547
|
+
({ className, children, ...props }, ref) => {
|
|
548
|
+
const ctx = React16__namespace.useContext(AccordionContext);
|
|
549
|
+
const value = React16__namespace.useContext(ItemContext);
|
|
550
|
+
const isOpen = ctx.open.includes(value);
|
|
551
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
552
|
+
"button",
|
|
553
|
+
{
|
|
554
|
+
ref,
|
|
555
|
+
type: "button",
|
|
556
|
+
"aria-expanded": isOpen,
|
|
557
|
+
onClick: () => ctx.toggle(value),
|
|
558
|
+
className: cn(
|
|
559
|
+
"w-full flex justify-between items-center gap-4 text-left px-[1.2rem] py-4 bg-card text-foreground text-[0.9rem] font-semibold cursor-pointer hover:bg-muted transition-colors",
|
|
560
|
+
className
|
|
561
|
+
),
|
|
562
|
+
...props,
|
|
563
|
+
children: [
|
|
564
|
+
children,
|
|
565
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
566
|
+
"svg",
|
|
567
|
+
{
|
|
568
|
+
className: cn("shrink-0 text-muted-foreground transition-transform duration-200", isOpen && "rotate-180"),
|
|
569
|
+
width: 18,
|
|
570
|
+
height: 18,
|
|
571
|
+
viewBox: "0 0 24 24",
|
|
572
|
+
fill: "none",
|
|
573
|
+
stroke: "currentColor",
|
|
574
|
+
strokeWidth: 2,
|
|
575
|
+
strokeLinecap: "round",
|
|
576
|
+
strokeLinejoin: "round",
|
|
577
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
|
|
578
|
+
}
|
|
579
|
+
)
|
|
580
|
+
]
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
);
|
|
585
|
+
AccordionTrigger.displayName = "AccordionTrigger";
|
|
586
|
+
var AccordionContent = React16__namespace.forwardRef(
|
|
587
|
+
({ className, children, ...props }, ref) => {
|
|
588
|
+
const ctx = React16__namespace.useContext(AccordionContext);
|
|
589
|
+
const value = React16__namespace.useContext(ItemContext);
|
|
590
|
+
const isOpen = ctx.open.includes(value);
|
|
591
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
592
|
+
"div",
|
|
593
|
+
{
|
|
594
|
+
ref,
|
|
595
|
+
className: cn("grid transition-[grid-template-rows] duration-200 ease-out", isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"),
|
|
596
|
+
...props,
|
|
597
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-[1.2rem] pb-[1.1rem] text-[0.85rem] text-muted-foreground", className), children }) })
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
);
|
|
602
|
+
AccordionContent.displayName = "AccordionContent";
|
|
603
|
+
var MenuContext = React16__namespace.createContext(null);
|
|
604
|
+
function DropdownMenu({ children, className }) {
|
|
605
|
+
const [open, setOpen] = React16__namespace.useState(false);
|
|
606
|
+
const ref = React16__namespace.useRef(null);
|
|
607
|
+
React16__namespace.useEffect(() => {
|
|
608
|
+
if (!open) return;
|
|
609
|
+
const onDoc = (e) => {
|
|
610
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
611
|
+
};
|
|
612
|
+
const onEsc = (e) => e.key === "Escape" && setOpen(false);
|
|
613
|
+
document.addEventListener("mousedown", onDoc);
|
|
614
|
+
document.addEventListener("keydown", onEsc);
|
|
615
|
+
return () => {
|
|
616
|
+
document.removeEventListener("mousedown", onDoc);
|
|
617
|
+
document.removeEventListener("keydown", onEsc);
|
|
618
|
+
};
|
|
619
|
+
}, [open]);
|
|
620
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MenuContext.Provider, { value: { open, setOpen }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-block", className), children }) });
|
|
621
|
+
}
|
|
622
|
+
var DropdownMenuTrigger = React16__namespace.forwardRef(({ onClick, ...props }, ref) => {
|
|
623
|
+
const ctx = React16__namespace.useContext(MenuContext);
|
|
624
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
625
|
+
"button",
|
|
626
|
+
{
|
|
627
|
+
ref,
|
|
628
|
+
type: "button",
|
|
629
|
+
"aria-haspopup": "menu",
|
|
630
|
+
"aria-expanded": ctx.open,
|
|
631
|
+
onClick: (e) => {
|
|
632
|
+
ctx.setOpen(!ctx.open);
|
|
633
|
+
onClick?.(e);
|
|
634
|
+
},
|
|
635
|
+
...props
|
|
636
|
+
}
|
|
637
|
+
);
|
|
638
|
+
});
|
|
639
|
+
DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
|
|
640
|
+
function DropdownMenuContent({ className, align = "start", children, ...props }) {
|
|
641
|
+
const ctx = React16__namespace.useContext(MenuContext);
|
|
642
|
+
if (!ctx.open) return null;
|
|
643
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
644
|
+
"div",
|
|
645
|
+
{
|
|
646
|
+
role: "menu",
|
|
647
|
+
className: cn(
|
|
648
|
+
"absolute top-[calc(100%+6px)] z-40 min-w-[200px] p-1.5 rounded-kj-md bg-surface border border-border shadow-kj-lg",
|
|
649
|
+
"animate-[kjpop_.12s_ease]",
|
|
650
|
+
align === "end" ? "right-0" : "left-0",
|
|
651
|
+
className
|
|
652
|
+
),
|
|
653
|
+
...props,
|
|
654
|
+
children
|
|
655
|
+
}
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
var DropdownMenuItem = React16__namespace.forwardRef(
|
|
659
|
+
({ className, danger, icon, children, onClick, ...props }, ref) => {
|
|
660
|
+
const ctx = React16__namespace.useContext(MenuContext);
|
|
661
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
ref,
|
|
665
|
+
type: "button",
|
|
666
|
+
role: "menuitem",
|
|
667
|
+
onClick: (e) => {
|
|
668
|
+
onClick?.(e);
|
|
669
|
+
ctx.setOpen(false);
|
|
670
|
+
},
|
|
671
|
+
className: cn(
|
|
672
|
+
"w-full flex items-center gap-2.5 text-left px-2.5 py-2 rounded-kj-sm text-[0.85rem] cursor-pointer transition-colors",
|
|
673
|
+
"[&_svg]:h-4 [&_svg]:w-4",
|
|
674
|
+
danger ? "text-danger hover:bg-danger-surface" : "text-foreground hover:bg-muted",
|
|
675
|
+
className
|
|
676
|
+
),
|
|
677
|
+
...props,
|
|
678
|
+
children: [
|
|
679
|
+
icon,
|
|
680
|
+
children
|
|
681
|
+
]
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
);
|
|
686
|
+
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
687
|
+
function DropdownMenuSeparator({ className }) {
|
|
688
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-px bg-border my-1.5", className), role: "separator" });
|
|
689
|
+
}
|
|
690
|
+
var Breadcrumb = React16__namespace.forwardRef(
|
|
691
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("nav", { ref, "aria-label": "Breadcrumb", className: cn("flex items-center gap-1.5 text-[0.85rem] text-muted-foreground", className), ...props, children })
|
|
692
|
+
);
|
|
693
|
+
Breadcrumb.displayName = "Breadcrumb";
|
|
694
|
+
var BreadcrumbItem = React16__namespace.forwardRef(
|
|
695
|
+
({ className, current, children, ...props }, ref) => {
|
|
696
|
+
if (current) {
|
|
697
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-current": "page", className: cn("text-foreground font-semibold", className), children });
|
|
698
|
+
}
|
|
699
|
+
return /* @__PURE__ */ jsxRuntime.jsx("a", { ref, className: cn("text-inherit no-underline hover:text-foreground transition-colors", className), ...props, children });
|
|
700
|
+
}
|
|
701
|
+
);
|
|
702
|
+
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
703
|
+
function BreadcrumbSeparator() {
|
|
704
|
+
return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-muted-foreground/70", children: "/" });
|
|
705
|
+
}
|
|
706
|
+
function range(start, end) {
|
|
707
|
+
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
708
|
+
}
|
|
709
|
+
function paginate(page, pageCount) {
|
|
710
|
+
if (pageCount <= 7) return range(1, pageCount);
|
|
711
|
+
const left = Math.max(2, page - 1);
|
|
712
|
+
const right = Math.min(pageCount - 1, page + 1);
|
|
713
|
+
const items = [1];
|
|
714
|
+
if (left > 2) items.push("\u2026");
|
|
715
|
+
items.push(...range(left, right));
|
|
716
|
+
if (right < pageCount - 1) items.push("\u2026");
|
|
717
|
+
items.push(pageCount);
|
|
718
|
+
return items;
|
|
719
|
+
}
|
|
720
|
+
var Chevron = ({ dir }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: dir === "left" ? "15 18 9 12 15 6" : "9 18 15 12 9 6" }) });
|
|
721
|
+
function Pagination({ page, pageCount, onPageChange, className }) {
|
|
722
|
+
const items = paginate(page, pageCount);
|
|
723
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-label": "Paginacja", className: cn("flex items-center gap-1", className), children: [
|
|
724
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Previous", disabled: page <= 1, onClick: () => onPageChange(page - 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "left" }) }),
|
|
725
|
+
items.map(
|
|
726
|
+
(it, i) => it === "\u2026" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-1 text-muted-foreground select-none", children: "\u2026" }, `e${i}`) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
727
|
+
Button,
|
|
728
|
+
{
|
|
729
|
+
variant: it === page ? "primary" : "ghost",
|
|
730
|
+
size: "icon-sm",
|
|
731
|
+
"aria-current": it === page ? "page" : void 0,
|
|
732
|
+
onClick: () => onPageChange(it),
|
|
733
|
+
children: it
|
|
734
|
+
},
|
|
735
|
+
it
|
|
736
|
+
)
|
|
737
|
+
),
|
|
738
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Next", disabled: page >= pageCount, onClick: () => onPageChange(page + 1), children: /* @__PURE__ */ jsxRuntime.jsx(Chevron, { dir: "right" }) })
|
|
739
|
+
] });
|
|
740
|
+
}
|
|
741
|
+
var TableWrap = React16__namespace.forwardRef(
|
|
742
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("border border-border rounded-kj-lg overflow-hidden", className), ...props })
|
|
743
|
+
);
|
|
744
|
+
TableWrap.displayName = "TableWrap";
|
|
745
|
+
var Table = React16__namespace.forwardRef(
|
|
746
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("table", { ref, className: cn("w-full border-collapse text-[0.85rem]", className), ...props })
|
|
747
|
+
);
|
|
748
|
+
Table.displayName = "Table";
|
|
749
|
+
var TableHeader = React16__namespace.forwardRef(
|
|
750
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("thead", { ref, className, ...props })
|
|
751
|
+
);
|
|
752
|
+
TableHeader.displayName = "TableHeader";
|
|
753
|
+
var TableBody = React16__namespace.forwardRef(
|
|
754
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { ref, className, ...props })
|
|
755
|
+
);
|
|
756
|
+
TableBody.displayName = "TableBody";
|
|
757
|
+
var TableRow = React16__namespace.forwardRef(
|
|
758
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("tr", { ref, className: cn("transition-colors hover:bg-muted/50", className), ...props })
|
|
759
|
+
);
|
|
760
|
+
TableRow.displayName = "TableRow";
|
|
761
|
+
var TableHead = React16__namespace.forwardRef(
|
|
762
|
+
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
763
|
+
"th",
|
|
764
|
+
{
|
|
765
|
+
ref,
|
|
766
|
+
className: cn(
|
|
767
|
+
"px-4 py-3 bg-muted border-b border-border text-[0.72rem] font-semibold uppercase tracking-[0.05em] text-muted-foreground",
|
|
768
|
+
numeric ? "text-right" : "text-left",
|
|
769
|
+
className
|
|
770
|
+
),
|
|
771
|
+
...props
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
);
|
|
775
|
+
TableHead.displayName = "TableHead";
|
|
776
|
+
var TableCell = React16__namespace.forwardRef(
|
|
777
|
+
({ className, numeric, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
778
|
+
"td",
|
|
779
|
+
{
|
|
780
|
+
ref,
|
|
781
|
+
className: cn(
|
|
782
|
+
"px-4 py-3 border-b border-border [tr:last-child_&]:border-b-0",
|
|
783
|
+
numeric && "text-right tabular-nums",
|
|
784
|
+
className
|
|
785
|
+
),
|
|
786
|
+
...props
|
|
787
|
+
}
|
|
788
|
+
)
|
|
789
|
+
);
|
|
790
|
+
TableCell.displayName = "TableCell";
|
|
791
|
+
function Tooltip({ content, children, className }) {
|
|
792
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("relative inline-flex group", className), tabIndex: 0, children: [
|
|
793
|
+
children,
|
|
794
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
795
|
+
"span",
|
|
796
|
+
{
|
|
797
|
+
role: "tooltip",
|
|
798
|
+
className: cn(
|
|
799
|
+
"pointer-events-none absolute bottom-[calc(100%+8px)] left-1/2 -translate-x-1/2 translate-y-1 whitespace-nowrap",
|
|
800
|
+
"rounded-kj-sm bg-foreground text-background text-xs font-medium px-2.5 py-1.5 shadow-kj-md",
|
|
801
|
+
"opacity-0 transition-all duration-150 group-hover:opacity-100 group-hover:translate-y-0 group-focus-visible:opacity-100 group-focus-visible:translate-y-0",
|
|
802
|
+
"after:content-[''] after:absolute after:top-full after:left-1/2 after:-translate-x-1/2 after:border-[5px] after:border-transparent after:border-t-foreground"
|
|
803
|
+
),
|
|
804
|
+
children: content
|
|
805
|
+
}
|
|
806
|
+
)
|
|
807
|
+
] });
|
|
808
|
+
}
|
|
809
|
+
function Modal({ open, onClose, children, width = 440, className }) {
|
|
810
|
+
React16__namespace.useEffect(() => {
|
|
811
|
+
if (!open) return;
|
|
812
|
+
const onEsc = (e) => e.key === "Escape" && onClose();
|
|
813
|
+
document.addEventListener("keydown", onEsc);
|
|
814
|
+
document.body.style.overflow = "hidden";
|
|
815
|
+
return () => {
|
|
816
|
+
document.removeEventListener("keydown", onEsc);
|
|
817
|
+
document.body.style.overflow = "";
|
|
818
|
+
};
|
|
819
|
+
}, [open, onClose]);
|
|
820
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
821
|
+
"div",
|
|
822
|
+
{
|
|
823
|
+
onClick: (e) => e.target === e.currentTarget && onClose(),
|
|
824
|
+
className: cn(
|
|
825
|
+
"fixed inset-0 z-[100] grid place-items-center p-6 backdrop-blur-[3px] transition-opacity duration-200",
|
|
826
|
+
"bg-[color-mix(in_oklch,#09090b_55%,transparent)]",
|
|
827
|
+
open ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
|
828
|
+
),
|
|
829
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
830
|
+
"div",
|
|
831
|
+
{
|
|
832
|
+
role: "dialog",
|
|
833
|
+
"aria-modal": "true",
|
|
834
|
+
style: { maxWidth: width },
|
|
835
|
+
className: cn(
|
|
836
|
+
"w-full p-7 rounded-kj-2xl bg-surface border border-border shadow-kj-lg transition-transform duration-200",
|
|
837
|
+
open ? "scale-100 translate-y-0" : "scale-95 translate-y-2",
|
|
838
|
+
className
|
|
839
|
+
),
|
|
840
|
+
children
|
|
841
|
+
}
|
|
842
|
+
)
|
|
843
|
+
}
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
function ModalTitle({ className, ...props }) {
|
|
847
|
+
return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("m-0 mb-2 text-[1.15rem] font-bold tracking-[-0.01em]", className), ...props });
|
|
848
|
+
}
|
|
849
|
+
function ModalDescription({ className, ...props }) {
|
|
850
|
+
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("m-0 text-[0.9rem] text-muted-foreground", className), ...props });
|
|
851
|
+
}
|
|
852
|
+
function ModalActions({ className, ...props }) {
|
|
853
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex gap-2.5 justify-end mt-6", className), ...props });
|
|
854
|
+
}
|
|
855
|
+
var ToastContext = React16__namespace.createContext(null);
|
|
856
|
+
function useToast() {
|
|
857
|
+
const ctx = React16__namespace.useContext(ToastContext);
|
|
858
|
+
if (!ctx) throw new Error("useToast must be used within <ToastProvider>");
|
|
859
|
+
return ctx;
|
|
860
|
+
}
|
|
861
|
+
var icons = {
|
|
862
|
+
default: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: "text-primary", children: [
|
|
863
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 16v-4M12 8h.01" })
|
|
865
|
+
] }),
|
|
866
|
+
success: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: "text-success", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6 9 17l-5-5" }) }),
|
|
867
|
+
danger: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", className: "text-danger", children: [
|
|
868
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
869
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 9-6 6M9 9l6 6" })
|
|
870
|
+
] })
|
|
871
|
+
};
|
|
872
|
+
var toneBorder = {
|
|
873
|
+
default: "border-l-primary",
|
|
874
|
+
success: "border-l-success",
|
|
875
|
+
danger: "border-l-danger"
|
|
876
|
+
};
|
|
877
|
+
function ToastProvider({ children }) {
|
|
878
|
+
const [items, setItems] = React16__namespace.useState([]);
|
|
879
|
+
const idRef = React16__namespace.useRef(0);
|
|
880
|
+
const remove = React16__namespace.useCallback((id) => {
|
|
881
|
+
setItems((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
|
|
882
|
+
setTimeout(() => setItems((prev) => prev.filter((t) => t.id !== id)), 250);
|
|
883
|
+
}, []);
|
|
884
|
+
const toast = React16__namespace.useCallback(
|
|
885
|
+
({ message, tone = "default", duration = 3200 }) => {
|
|
886
|
+
const id = ++idRef.current;
|
|
887
|
+
setItems((prev) => [...prev, { id, message, tone, duration }]);
|
|
888
|
+
if (duration > 0) setTimeout(() => remove(id), duration);
|
|
889
|
+
},
|
|
890
|
+
[remove]
|
|
891
|
+
);
|
|
892
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast }, children: [
|
|
893
|
+
children,
|
|
894
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed bottom-6 right-6 z-[200] flex flex-col gap-2.5", children: items.map((t) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
895
|
+
"div",
|
|
896
|
+
{
|
|
897
|
+
role: "status",
|
|
898
|
+
onClick: () => remove(t.id),
|
|
899
|
+
className: cn(
|
|
900
|
+
"flex items-center gap-2.5 min-w-[280px] px-4 py-3 cursor-pointer",
|
|
901
|
+
"bg-surface border border-border border-l-[3px] rounded-kj-md shadow-kj-lg text-[0.85rem] font-medium",
|
|
902
|
+
toneBorder[t.tone],
|
|
903
|
+
t.leaving ? "animate-[kjtoastout_.25s_ease_forwards]" : "animate-[kjtoastin_.25s_ease]"
|
|
904
|
+
),
|
|
905
|
+
children: [
|
|
906
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "grid place-items-center", children: icons[t.tone] }),
|
|
907
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: t.message })
|
|
908
|
+
]
|
|
909
|
+
},
|
|
910
|
+
t.id
|
|
911
|
+
)) })
|
|
912
|
+
] });
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
exports.Accordion = Accordion;
|
|
916
|
+
exports.AccordionContent = AccordionContent;
|
|
917
|
+
exports.AccordionItem = AccordionItem;
|
|
918
|
+
exports.AccordionTrigger = AccordionTrigger;
|
|
919
|
+
exports.Alert = Alert;
|
|
920
|
+
exports.Avatar = Avatar;
|
|
921
|
+
exports.AvatarGroup = AvatarGroup;
|
|
922
|
+
exports.Badge = Badge;
|
|
923
|
+
exports.Breadcrumb = Breadcrumb;
|
|
924
|
+
exports.BreadcrumbItem = BreadcrumbItem;
|
|
925
|
+
exports.BreadcrumbSeparator = BreadcrumbSeparator;
|
|
926
|
+
exports.Button = Button;
|
|
927
|
+
exports.Card = Card;
|
|
928
|
+
exports.CardContent = CardContent;
|
|
929
|
+
exports.CardDescription = CardDescription;
|
|
930
|
+
exports.CardFooter = CardFooter;
|
|
931
|
+
exports.CardHeader = CardHeader;
|
|
932
|
+
exports.CardTitle = CardTitle;
|
|
933
|
+
exports.Checkbox = Checkbox;
|
|
934
|
+
exports.DropdownMenu = DropdownMenu;
|
|
935
|
+
exports.DropdownMenuContent = DropdownMenuContent;
|
|
936
|
+
exports.DropdownMenuItem = DropdownMenuItem;
|
|
937
|
+
exports.DropdownMenuSeparator = DropdownMenuSeparator;
|
|
938
|
+
exports.DropdownMenuTrigger = DropdownMenuTrigger;
|
|
939
|
+
exports.Field = Field;
|
|
940
|
+
exports.Hint = Hint;
|
|
941
|
+
exports.Input = Input;
|
|
942
|
+
exports.Label = Label;
|
|
943
|
+
exports.Modal = Modal;
|
|
944
|
+
exports.ModalActions = ModalActions;
|
|
945
|
+
exports.ModalDescription = ModalDescription;
|
|
946
|
+
exports.ModalTitle = ModalTitle;
|
|
947
|
+
exports.Pagination = Pagination;
|
|
948
|
+
exports.Progress = Progress;
|
|
949
|
+
exports.Radio = Radio;
|
|
950
|
+
exports.Segmented = Segmented;
|
|
951
|
+
exports.Select = Select;
|
|
952
|
+
exports.Slider = Slider;
|
|
953
|
+
exports.Spinner = Spinner;
|
|
954
|
+
exports.Stat = Stat;
|
|
955
|
+
exports.Switch = Switch;
|
|
956
|
+
exports.Table = Table;
|
|
957
|
+
exports.TableBody = TableBody;
|
|
958
|
+
exports.TableCell = TableCell;
|
|
959
|
+
exports.TableHead = TableHead;
|
|
960
|
+
exports.TableHeader = TableHeader;
|
|
961
|
+
exports.TableRow = TableRow;
|
|
962
|
+
exports.TableWrap = TableWrap;
|
|
963
|
+
exports.Tabs = Tabs;
|
|
964
|
+
exports.TabsContent = TabsContent;
|
|
965
|
+
exports.TabsList = TabsList;
|
|
966
|
+
exports.TabsTrigger = TabsTrigger;
|
|
967
|
+
exports.Textarea = Textarea;
|
|
968
|
+
exports.ToastProvider = ToastProvider;
|
|
969
|
+
exports.Tooltip = Tooltip;
|
|
970
|
+
exports.badgeVariants = badgeVariants;
|
|
971
|
+
exports.buttonVariants = buttonVariants;
|
|
972
|
+
exports.cn = cn;
|
|
973
|
+
exports.sliderThumbCSS = sliderThumbCSS;
|
|
974
|
+
exports.useToast = useToast;
|
|
975
|
+
//# sourceMappingURL=index.cjs.map
|
|
976
|
+
//# sourceMappingURL=index.cjs.map
|