@apotech-os/ui-sdk 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/dist/index.cjs ADDED
@@ -0,0 +1,371 @@
1
+ 'use strict';
2
+
3
+ var clsx = require('clsx');
4
+ var tailwindMerge = require('tailwind-merge');
5
+ var React = 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 React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+
29
+ // src/cn.ts
30
+ function cn(...inputs) {
31
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
32
+ }
33
+ var AppContextInternalCtx = React.createContext(null);
34
+ var AppContextProvider = AppContextInternalCtx.Provider;
35
+ function useAppContext() {
36
+ const ctx = React.useContext(AppContextInternalCtx);
37
+ if (!ctx) throw new Error("useAppContext must be used inside an app page mounted by the shell");
38
+ return ctx;
39
+ }
40
+ var AppApiCtx = React.createContext(null);
41
+ var AppApiProvider = AppApiCtx.Provider;
42
+ function useAppApi() {
43
+ const client = React.useContext(AppApiCtx);
44
+ if (!client) throw new Error("useAppApi must be used inside an app page mounted by the shell");
45
+ return client;
46
+ }
47
+ var buttonVariants = classVarianceAuthority.cva(
48
+ "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
49
+ {
50
+ variants: {
51
+ variant: {
52
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
53
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
54
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
55
+ ghost: "hover:bg-accent hover:text-accent-foreground",
56
+ destructive: "bg-destructive text-white hover:bg-destructive/90"
57
+ },
58
+ size: {
59
+ default: "h-9 px-4 py-2",
60
+ sm: "h-8 rounded-md px-3 text-xs",
61
+ lg: "h-10 rounded-md px-6",
62
+ icon: "h-9 w-9"
63
+ }
64
+ },
65
+ defaultVariants: { variant: "default", size: "default" }
66
+ }
67
+ );
68
+ var Button = React__namespace.forwardRef(
69
+ ({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("button", { ref, className: cn(buttonVariants({ variant, size, className })), ...props })
70
+ );
71
+ Button.displayName = "Button";
72
+ var badgeVariants = classVarianceAuthority.cva(
73
+ "inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap",
74
+ {
75
+ variants: {
76
+ variant: {
77
+ neutral: "border-border bg-muted text-muted-foreground",
78
+ brand: "border-primary/20 bg-primary/10 text-primary",
79
+ success: "border-status-success/25 bg-status-success/10 text-status-success",
80
+ warning: "border-status-pending/30 bg-status-pending/10 text-status-pending",
81
+ danger: "border-status-blocked/25 bg-status-blocked/10 text-status-blocked",
82
+ info: "border-status-info/25 bg-status-info/10 text-status-info",
83
+ outline: "border-border bg-transparent text-muted-foreground"
84
+ }
85
+ },
86
+ defaultVariants: { variant: "neutral" }
87
+ }
88
+ );
89
+ function Badge({ className, variant, dot, children, ...props }) {
90
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(badgeVariants({ variant }), className), ...props, children: [
91
+ dot && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-current" }),
92
+ children
93
+ ] });
94
+ }
95
+ function Card({ className, ...props }) {
96
+ return /* @__PURE__ */ jsxRuntime.jsx(
97
+ "div",
98
+ {
99
+ className: cn("rounded-xl border bg-card text-card-foreground shadow-sm", className),
100
+ ...props
101
+ }
102
+ );
103
+ }
104
+ function CardHeader({ className, ...props }) {
105
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 p-6", className), ...props });
106
+ }
107
+ function CardTitle({ className, ...props }) {
108
+ return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props });
109
+ }
110
+ function CardContent({ className, ...props }) {
111
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 pt-0", className), ...props });
112
+ }
113
+ var Input = React__namespace.forwardRef(
114
+ ({ className, type, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
115
+ "input",
116
+ {
117
+ type,
118
+ className: cn(
119
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
120
+ className
121
+ ),
122
+ ref,
123
+ ...props
124
+ }
125
+ )
126
+ );
127
+ Input.displayName = "Input";
128
+ function Table({ className, ...props }) {
129
+ return /* @__PURE__ */ jsxRuntime.jsx("table", { className: cn("w-full text-sm", className), ...props });
130
+ }
131
+ function TableHeader({ className, ...props }) {
132
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { className: cn("[&_tr]:border-b", className), ...props });
133
+ }
134
+ function TableBody({ className, ...props }) {
135
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: cn("[&_tr:last-child]:border-0", className), ...props });
136
+ }
137
+ function TableRow({ className, ...props }) {
138
+ return /* @__PURE__ */ jsxRuntime.jsx(
139
+ "tr",
140
+ {
141
+ className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className),
142
+ ...props
143
+ }
144
+ );
145
+ }
146
+ function TableHead({ className, ...props }) {
147
+ return /* @__PURE__ */ jsxRuntime.jsx(
148
+ "th",
149
+ {
150
+ className: cn("h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground", className),
151
+ ...props
152
+ }
153
+ );
154
+ }
155
+ function TableCell({ className, ...props }) {
156
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { className: cn("p-4 align-middle", className), ...props });
157
+ }
158
+ var Select = React__namespace.forwardRef(
159
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
160
+ "select",
161
+ {
162
+ ref,
163
+ className: cn(
164
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
165
+ className
166
+ ),
167
+ ...props,
168
+ children
169
+ }
170
+ )
171
+ );
172
+ Select.displayName = "Select";
173
+ var TabsContext = React__namespace.createContext(null);
174
+ function useTabsContext() {
175
+ const ctx = React__namespace.useContext(TabsContext);
176
+ if (!ctx) throw new Error("Tabs sub-component must be used within <Tabs>");
177
+ return ctx;
178
+ }
179
+ function Tabs({ defaultValue, value, onValueChange, className, children }) {
180
+ const [internal, setInternal] = React__namespace.useState(defaultValue ?? "");
181
+ const current = value ?? internal;
182
+ const setValue = (v) => {
183
+ setInternal(v);
184
+ onValueChange?.(v);
185
+ };
186
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className, children }) });
187
+ }
188
+ function TabsList({ className, children }) {
189
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("inline-flex items-center gap-1 rounded-lg bg-muted p-1", className), children });
190
+ }
191
+ function TabsTrigger({
192
+ value,
193
+ className,
194
+ children
195
+ }) {
196
+ const { value: current, setValue } = useTabsContext();
197
+ const active = current === value;
198
+ return /* @__PURE__ */ jsxRuntime.jsx(
199
+ "button",
200
+ {
201
+ type: "button",
202
+ onClick: () => setValue(value),
203
+ className: cn(
204
+ "rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
205
+ active ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
206
+ className
207
+ ),
208
+ children
209
+ }
210
+ );
211
+ }
212
+ function TabsContent({
213
+ value,
214
+ className,
215
+ children
216
+ }) {
217
+ const { value: current } = useTabsContext();
218
+ if (current !== value) return null;
219
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children });
220
+ }
221
+ function Modal({ open, onClose, title, children, className }) {
222
+ if (!open) return null;
223
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
224
+ /* @__PURE__ */ jsxRuntime.jsx(
225
+ "button",
226
+ {
227
+ type: "button",
228
+ "aria-label": "Close",
229
+ className: "absolute inset-0 cursor-default bg-foreground/40",
230
+ onClick: onClose
231
+ }
232
+ ),
233
+ /* @__PURE__ */ jsxRuntime.jsxs(
234
+ "div",
235
+ {
236
+ role: "dialog",
237
+ "aria-modal": true,
238
+ className: cn("relative z-10 w-full max-w-md rounded-xl border bg-card p-5 shadow-lg", className),
239
+ children: [
240
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mb-3 text-base font-semibold", children: title }),
241
+ children
242
+ ]
243
+ }
244
+ )
245
+ ] });
246
+ }
247
+ var spinnerSizes = { sm: "size-4", md: "size-6", lg: "size-8" };
248
+ function Spinner({ className, size = "md" }) {
249
+ return /* @__PURE__ */ jsxRuntime.jsxs(
250
+ "svg",
251
+ {
252
+ className: cn("animate-spin text-muted-foreground", spinnerSizes[size], className),
253
+ xmlns: "http://www.w3.org/2000/svg",
254
+ fill: "none",
255
+ viewBox: "0 0 24 24",
256
+ "aria-label": "Loading",
257
+ role: "status",
258
+ children: [
259
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
260
+ /* @__PURE__ */ jsxRuntime.jsx(
261
+ "path",
262
+ {
263
+ className: "opacity-75",
264
+ fill: "currentColor",
265
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
266
+ }
267
+ )
268
+ ]
269
+ }
270
+ );
271
+ }
272
+ var Link = React__namespace.forwardRef(
273
+ ({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
274
+ "a",
275
+ {
276
+ ref,
277
+ className: cn(
278
+ "underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
279
+ variant === "default" ? "text-primary" : "text-muted-foreground",
280
+ className
281
+ ),
282
+ ...props
283
+ }
284
+ )
285
+ );
286
+ Link.displayName = "Link";
287
+ function Switch({ checked = false, onCheckedChange, disabled, className, ...props }) {
288
+ return /* @__PURE__ */ jsxRuntime.jsx(
289
+ "button",
290
+ {
291
+ type: "button",
292
+ role: "switch",
293
+ "aria-checked": checked,
294
+ disabled,
295
+ onClick: () => onCheckedChange?.(!checked),
296
+ className: cn(
297
+ "relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
298
+ checked ? "bg-primary" : "bg-input",
299
+ className
300
+ ),
301
+ ...props,
302
+ children: /* @__PURE__ */ jsxRuntime.jsx(
303
+ "span",
304
+ {
305
+ className: cn(
306
+ "inline-block size-4 transform rounded-full bg-white shadow transition-transform",
307
+ checked ? "translate-x-4" : "translate-x-0.5"
308
+ )
309
+ }
310
+ )
311
+ }
312
+ );
313
+ }
314
+ function DateRangePicker({ value, onChange, className, disabled }) {
315
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
316
+ /* @__PURE__ */ jsxRuntime.jsx(
317
+ "input",
318
+ {
319
+ type: "date",
320
+ disabled,
321
+ value: value.from,
322
+ max: value.to || void 0,
323
+ onChange: (e) => onChange({ ...value, from: e.target.value }),
324
+ className: "flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
325
+ }
326
+ ),
327
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm", children: "\u2192" }),
328
+ /* @__PURE__ */ jsxRuntime.jsx(
329
+ "input",
330
+ {
331
+ type: "date",
332
+ disabled,
333
+ value: value.to,
334
+ min: value.from || void 0,
335
+ onChange: (e) => onChange({ ...value, to: e.target.value }),
336
+ className: "flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
337
+ }
338
+ )
339
+ ] });
340
+ }
341
+
342
+ exports.AppApiProvider = AppApiProvider;
343
+ exports.AppContextProvider = AppContextProvider;
344
+ exports.Badge = Badge;
345
+ exports.Button = Button;
346
+ exports.Card = Card;
347
+ exports.CardContent = CardContent;
348
+ exports.CardHeader = CardHeader;
349
+ exports.CardTitle = CardTitle;
350
+ exports.DateRangePicker = DateRangePicker;
351
+ exports.Input = Input;
352
+ exports.Link = Link;
353
+ exports.Modal = Modal;
354
+ exports.Select = Select;
355
+ exports.Spinner = Spinner;
356
+ exports.Switch = Switch;
357
+ exports.Table = Table;
358
+ exports.TableBody = TableBody;
359
+ exports.TableCell = TableCell;
360
+ exports.TableHead = TableHead;
361
+ exports.TableHeader = TableHeader;
362
+ exports.TableRow = TableRow;
363
+ exports.Tabs = Tabs;
364
+ exports.TabsContent = TabsContent;
365
+ exports.TabsList = TabsList;
366
+ exports.TabsTrigger = TabsTrigger;
367
+ exports.cn = cn;
368
+ exports.useAppApi = useAppApi;
369
+ exports.useAppContext = useAppContext;
370
+ //# sourceMappingURL=index.cjs.map
371
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cn.ts","../src/hooks.ts","../src/components.tsx"],"names":["twMerge","clsx","createContext","useContext","cva","React","jsx","jsxs"],"mappings":"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","file":"index.cjs","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * Runtime hooks provided by the shell via @apotech-os/ui-sdk.\n *\n * These hooks are implemented by the shell and injected at runtime via the\n * import map. App pages call them without knowing the shell internals.\n *\n * The default implementations throw if called outside of the shell context\n * (which should never happen in production — the shell always provides them\n * via the import map before mounting an app page).\n */\n\nimport { useContext, createContext } from 'react';\n\n// ---------------------------------------------------------------------------\n// AppContext\n// ---------------------------------------------------------------------------\n\nexport interface AppContextValue {\n /** The slug of the installed app owning this page. */\n appSlug: string;\n /** The page path within the app (e.g. 'attribution'). */\n pagePath: string;\n /** The active space id, when applicable. */\n spaceId?: string;\n}\n\nconst AppContextInternalCtx = createContext<AppContextValue | null>(null);\n\nexport const AppContextProvider = AppContextInternalCtx.Provider;\n\n/** Returns context info for the current app page (appSlug, pagePath, spaceId). */\nexport function useAppContext(): AppContextValue {\n const ctx = useContext(AppContextInternalCtx);\n if (!ctx) throw new Error('useAppContext must be used inside an app page mounted by the shell');\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// AppApi\n// ---------------------------------------------------------------------------\n\nexport interface AppApiClient {\n /**\n * Perform a GET request to a platform-data endpoint.\n * The session cookie is forwarded automatically (same-origin, withCredentials).\n */\n get<T>(path: string, params?: Record<string, string>): Promise<T>;\n /**\n * Perform a POST request to a platform-data endpoint.\n */\n post<T>(path: string, body?: unknown): Promise<T>;\n}\n\nconst AppApiCtx = createContext<AppApiClient | null>(null);\n\nexport const AppApiProvider = AppApiCtx.Provider;\n\n/**\n * Returns an API client scoped to the current user session.\n * Requests go to /api/data/* with the session cookie (RBAC applies server-side).\n */\nexport function useAppApi(): AppApiClient {\n const client = useContext(AppApiCtx);\n if (!client) throw new Error('useAppApi must be used inside an app page mounted by the shell');\n return client;\n}\n","/**\n * Design system components exported by @apotech-os/ui-sdk.\n *\n * These are minimal self-contained copies of the shell's component library.\n * They use the same Tailwind utility classes as the shell — Tailwind classes\n * are plain strings and work without any build step when the shell's stylesheet\n * is loaded (which it is, since these pages run inside the shell).\n *\n * Strategy note:\n * - Not imported from apps/web (would create a circular dep pkg → app).\n * - Copied/adapted here to keep the SDK self-contained and publishable.\n * - The exhaustive component inventory is tracked in #75.\n */\n\nimport { type VariantProps, cva } from 'class-variance-authority';\nimport * as React from 'react';\nimport { cn } from './cn';\n\n// ---------------------------------------------------------------------------\n// Button\n// ---------------------------------------------------------------------------\n\nconst buttonVariants = cva(\n 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n destructive: 'bg-destructive text-white hover:bg-destructive/90',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-10 rounded-md px-6',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, ...props }, ref) => (\n <button ref={ref} className={cn(buttonVariants({ variant, size, className }))} {...props} />\n ),\n);\nButton.displayName = 'Button';\n\n// ---------------------------------------------------------------------------\n// Badge\n// ---------------------------------------------------------------------------\n\nconst badgeVariants = cva(\n 'inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap',\n {\n variants: {\n variant: {\n neutral: 'border-border bg-muted text-muted-foreground',\n brand: 'border-primary/20 bg-primary/10 text-primary',\n success: 'border-status-success/25 bg-status-success/10 text-status-success',\n warning: 'border-status-pending/30 bg-status-pending/10 text-status-pending',\n danger: 'border-status-blocked/25 bg-status-blocked/10 text-status-blocked',\n info: 'border-status-info/25 bg-status-info/10 text-status-info',\n outline: 'border-border bg-transparent text-muted-foreground',\n },\n },\n defaultVariants: { variant: 'neutral' },\n },\n);\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {\n dot?: boolean;\n}\n\nexport function Badge({ className, variant, dot, children, ...props }: BadgeProps) {\n return (\n <span className={cn(badgeVariants({ variant }), className)} {...props}>\n {dot && <span className=\"size-1.5 rounded-full bg-current\" />}\n {children}\n </span>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Card\n// ---------------------------------------------------------------------------\n\nexport function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('rounded-xl border bg-card text-card-foreground shadow-sm', className)}\n {...props}\n />\n );\n}\n\nexport function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />;\n}\n\nexport function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {\n return <h3 className={cn('text-lg font-semibold leading-none tracking-tight', className)} {...props} />;\n}\n\nexport function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('p-6 pt-0', className)} {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input\n// ---------------------------------------------------------------------------\n\nexport const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(\n ({ className, type, ...props }, ref) => (\n <input\n type={type}\n className={cn(\n 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n ref={ref}\n {...props}\n />\n ),\n);\nInput.displayName = 'Input';\n\n// ---------------------------------------------------------------------------\n// Table\n// ---------------------------------------------------------------------------\n\nexport function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) {\n return <table className={cn('w-full text-sm', className)} {...props} />;\n}\n\nexport function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) {\n return <thead className={cn('[&_tr]:border-b', className)} {...props} />;\n}\n\nexport function TableBody({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) {\n return <tbody className={cn('[&_tr:last-child]:border-0', className)} {...props} />;\n}\n\nexport function TableRow({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>) {\n return (\n <tr\n className={cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', className)}\n {...props}\n />\n );\n}\n\nexport function TableHead({ className, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>) {\n return (\n <th\n className={cn('h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport function TableCell({ className, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>) {\n return <td className={cn('p-4 align-middle', className)} {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Select\n// ---------------------------------------------------------------------------\n\nexport interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {}\n\nexport const Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, children, ...props }, ref) => (\n <select\n ref={ref}\n className={cn(\n 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </select>\n ),\n);\nSelect.displayName = 'Select';\n\n// ---------------------------------------------------------------------------\n// Tabs\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string;\n setValue: (v: string) => void;\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext);\n if (!ctx) throw new Error('Tabs sub-component must be used within <Tabs>');\n return ctx;\n}\n\nexport interface TabsProps {\n defaultValue?: string;\n value?: string;\n onValueChange?: (v: string) => void;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps) {\n const [internal, setInternal] = React.useState(defaultValue ?? '');\n const current = value ?? internal;\n const setValue = (v: string) => {\n setInternal(v);\n onValueChange?.(v);\n };\n return (\n <TabsContext.Provider value={{ value: current, setValue }}>\n <div className={className}>{children}</div>\n </TabsContext.Provider>\n );\n}\n\nexport function TabsList({ className, children }: { className?: string; children: React.ReactNode }) {\n return (\n <div className={cn('inline-flex items-center gap-1 rounded-lg bg-muted p-1', className)}>\n {children}\n </div>\n );\n}\n\nexport function TabsTrigger({\n value,\n className,\n children,\n}: {\n value: string;\n className?: string;\n children: React.ReactNode;\n}) {\n const { value: current, setValue } = useTabsContext();\n const active = current === value;\n return (\n <button\n type=\"button\"\n onClick={() => setValue(value)}\n className={cn(\n 'rounded-md px-3 py-1.5 text-sm font-medium transition-colors',\n active ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n className,\n )}\n >\n {children}\n </button>\n );\n}\n\nexport function TabsContent({\n value,\n className,\n children,\n}: {\n value: string;\n className?: string;\n children: React.ReactNode;\n}) {\n const { value: current } = useTabsContext();\n if (current !== value) return null;\n return <div className={className}>{children}</div>;\n}\n\n// ---------------------------------------------------------------------------\n// Modal (controlled, no Radix)\n// ---------------------------------------------------------------------------\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function Modal({ open, onClose, title, children, className }: ModalProps) {\n if (!open) return null;\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <button\n type=\"button\"\n aria-label=\"Close\"\n className=\"absolute inset-0 cursor-default bg-foreground/40\"\n onClick={onClose}\n />\n <div\n role=\"dialog\"\n aria-modal\n className={cn('relative z-10 w-full max-w-md rounded-xl border bg-card p-5 shadow-lg', className)}\n >\n {title && <h2 className=\"mb-3 text-base font-semibold\">{title}</h2>}\n {children}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Spinner\n// ---------------------------------------------------------------------------\n\nexport interface SpinnerProps {\n className?: string;\n size?: 'sm' | 'md' | 'lg';\n}\n\nconst spinnerSizes = { sm: 'size-4', md: 'size-6', lg: 'size-8' };\n\nexport function Spinner({ className, size = 'md' }: SpinnerProps) {\n return (\n <svg\n className={cn('animate-spin text-muted-foreground', spinnerSizes[size], className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-label=\"Loading\"\n role=\"status\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Link\n// ---------------------------------------------------------------------------\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n variant?: 'default' | 'muted';\n}\n\nexport const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, variant = 'default', ...props }, ref) => (\n <a\n ref={ref}\n className={cn(\n 'underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n variant === 'default' ? 'text-primary' : 'text-muted-foreground',\n className,\n )}\n {...props}\n />\n ),\n);\nLink.displayName = 'Link';\n\n// ---------------------------------------------------------------------------\n// Switch\n// ---------------------------------------------------------------------------\n\nexport interface SwitchProps {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n 'aria-label'?: string;\n}\n\nexport function Switch({ checked = false, onCheckedChange, disabled, className, ...props }: SwitchProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled}\n onClick={() => onCheckedChange?.(!checked)}\n className={cn(\n 'relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n checked ? 'bg-primary' : 'bg-input',\n className,\n )}\n {...props}\n >\n <span\n className={cn(\n 'inline-block size-4 transform rounded-full bg-white shadow transition-transform',\n checked ? 'translate-x-4' : 'translate-x-0.5',\n )}\n />\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// DateRangePicker\n// ---------------------------------------------------------------------------\n\nexport interface DateRange {\n from: string;\n to: string;\n}\n\nexport interface DateRangePickerProps {\n value: DateRange;\n onChange: (range: DateRange) => void;\n className?: string;\n disabled?: boolean;\n}\n\n/** Minimal controlled date-range picker using two native date inputs. */\nexport function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps) {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n <input\n type=\"date\"\n disabled={disabled}\n value={value.from}\n max={value.to || undefined}\n onChange={(e) => onChange({ ...value, from: e.target.value })}\n className=\"flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n <span className=\"text-muted-foreground text-sm\">→</span>\n <input\n type=\"date\"\n disabled={disabled}\n value={value.to}\n min={value.from || undefined}\n onChange={(e) => onChange({ ...value, to: e.target.value })}\n className=\"flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n );\n}\n"]}
@@ -0,0 +1,135 @@
1
+ import { ClassValue } from 'clsx';
2
+ import * as React from 'react';
3
+ import * as class_variance_authority_types from 'class-variance-authority/types';
4
+ import { VariantProps } from 'class-variance-authority';
5
+
6
+ declare function cn(...inputs: ClassValue[]): string;
7
+
8
+ /**
9
+ * Runtime hooks provided by the shell via @apotech-os/ui-sdk.
10
+ *
11
+ * These hooks are implemented by the shell and injected at runtime via the
12
+ * import map. App pages call them without knowing the shell internals.
13
+ *
14
+ * The default implementations throw if called outside of the shell context
15
+ * (which should never happen in production — the shell always provides them
16
+ * via the import map before mounting an app page).
17
+ */
18
+ interface AppContextValue {
19
+ /** The slug of the installed app owning this page. */
20
+ appSlug: string;
21
+ /** The page path within the app (e.g. 'attribution'). */
22
+ pagePath: string;
23
+ /** The active space id, when applicable. */
24
+ spaceId?: string;
25
+ }
26
+ declare const AppContextProvider: React.Provider<AppContextValue | null>;
27
+ /** Returns context info for the current app page (appSlug, pagePath, spaceId). */
28
+ declare function useAppContext(): AppContextValue;
29
+ interface AppApiClient {
30
+ /**
31
+ * Perform a GET request to a platform-data endpoint.
32
+ * The session cookie is forwarded automatically (same-origin, withCredentials).
33
+ */
34
+ get<T>(path: string, params?: Record<string, string>): Promise<T>;
35
+ /**
36
+ * Perform a POST request to a platform-data endpoint.
37
+ */
38
+ post<T>(path: string, body?: unknown): Promise<T>;
39
+ }
40
+ declare const AppApiProvider: React.Provider<AppApiClient | null>;
41
+ /**
42
+ * Returns an API client scoped to the current user session.
43
+ * Requests go to /api/data/* with the session cookie (RBAC applies server-side).
44
+ */
45
+ declare function useAppApi(): AppApiClient;
46
+
47
+ declare const buttonVariants: (props?: ({
48
+ variant?: "default" | "secondary" | "outline" | "ghost" | "destructive" | null | undefined;
49
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
50
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
51
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
52
+ }
53
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
54
+ declare const badgeVariants: (props?: ({
55
+ variant?: "outline" | "neutral" | "brand" | "success" | "warning" | "danger" | "info" | null | undefined;
56
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
57
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
58
+ dot?: boolean;
59
+ }
60
+ declare function Badge({ className, variant, dot, children, ...props }: BadgeProps): React.JSX.Element;
61
+ declare function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
62
+ declare function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
63
+ declare function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): React.JSX.Element;
64
+ declare function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
65
+ declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement>>;
66
+ declare function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>): React.JSX.Element;
67
+ declare function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
68
+ declare function TableBody({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
69
+ declare function TableRow({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>): React.JSX.Element;
70
+ declare function TableHead({ className, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
71
+ declare function TableCell({ className, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
72
+ interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
73
+ }
74
+ declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLSelectElement>>;
75
+ interface TabsProps {
76
+ defaultValue?: string;
77
+ value?: string;
78
+ onValueChange?: (v: string) => void;
79
+ className?: string;
80
+ children: React.ReactNode;
81
+ }
82
+ declare function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps): React.JSX.Element;
83
+ declare function TabsList({ className, children }: {
84
+ className?: string;
85
+ children: React.ReactNode;
86
+ }): React.JSX.Element;
87
+ declare function TabsTrigger({ value, className, children, }: {
88
+ value: string;
89
+ className?: string;
90
+ children: React.ReactNode;
91
+ }): React.JSX.Element;
92
+ declare function TabsContent({ value, className, children, }: {
93
+ value: string;
94
+ className?: string;
95
+ children: React.ReactNode;
96
+ }): React.JSX.Element | null;
97
+ interface ModalProps {
98
+ open: boolean;
99
+ onClose: () => void;
100
+ title?: React.ReactNode;
101
+ children: React.ReactNode;
102
+ className?: string;
103
+ }
104
+ declare function Modal({ open, onClose, title, children, className }: ModalProps): React.JSX.Element | null;
105
+ interface SpinnerProps {
106
+ className?: string;
107
+ size?: 'sm' | 'md' | 'lg';
108
+ }
109
+ declare function Spinner({ className, size }: SpinnerProps): React.JSX.Element;
110
+ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
111
+ variant?: 'default' | 'muted';
112
+ }
113
+ declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
114
+ interface SwitchProps {
115
+ checked?: boolean;
116
+ onCheckedChange?: (checked: boolean) => void;
117
+ disabled?: boolean;
118
+ className?: string;
119
+ 'aria-label'?: string;
120
+ }
121
+ declare function Switch({ checked, onCheckedChange, disabled, className, ...props }: SwitchProps): React.JSX.Element;
122
+ interface DateRange {
123
+ from: string;
124
+ to: string;
125
+ }
126
+ interface DateRangePickerProps {
127
+ value: DateRange;
128
+ onChange: (range: DateRange) => void;
129
+ className?: string;
130
+ disabled?: boolean;
131
+ }
132
+ /** Minimal controlled date-range picker using two native date inputs. */
133
+ declare function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps): React.JSX.Element;
134
+
135
+ export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type DateRange, DateRangePicker, type DateRangePickerProps, Input, Link, type LinkProps, Modal, type ModalProps, Select, type SelectProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, cn, useAppApi, useAppContext };
@@ -0,0 +1,135 @@
1
+ import { ClassValue } from 'clsx';
2
+ import * as React from 'react';
3
+ import * as class_variance_authority_types from 'class-variance-authority/types';
4
+ import { VariantProps } from 'class-variance-authority';
5
+
6
+ declare function cn(...inputs: ClassValue[]): string;
7
+
8
+ /**
9
+ * Runtime hooks provided by the shell via @apotech-os/ui-sdk.
10
+ *
11
+ * These hooks are implemented by the shell and injected at runtime via the
12
+ * import map. App pages call them without knowing the shell internals.
13
+ *
14
+ * The default implementations throw if called outside of the shell context
15
+ * (which should never happen in production — the shell always provides them
16
+ * via the import map before mounting an app page).
17
+ */
18
+ interface AppContextValue {
19
+ /** The slug of the installed app owning this page. */
20
+ appSlug: string;
21
+ /** The page path within the app (e.g. 'attribution'). */
22
+ pagePath: string;
23
+ /** The active space id, when applicable. */
24
+ spaceId?: string;
25
+ }
26
+ declare const AppContextProvider: React.Provider<AppContextValue | null>;
27
+ /** Returns context info for the current app page (appSlug, pagePath, spaceId). */
28
+ declare function useAppContext(): AppContextValue;
29
+ interface AppApiClient {
30
+ /**
31
+ * Perform a GET request to a platform-data endpoint.
32
+ * The session cookie is forwarded automatically (same-origin, withCredentials).
33
+ */
34
+ get<T>(path: string, params?: Record<string, string>): Promise<T>;
35
+ /**
36
+ * Perform a POST request to a platform-data endpoint.
37
+ */
38
+ post<T>(path: string, body?: unknown): Promise<T>;
39
+ }
40
+ declare const AppApiProvider: React.Provider<AppApiClient | null>;
41
+ /**
42
+ * Returns an API client scoped to the current user session.
43
+ * Requests go to /api/data/* with the session cookie (RBAC applies server-side).
44
+ */
45
+ declare function useAppApi(): AppApiClient;
46
+
47
+ declare const buttonVariants: (props?: ({
48
+ variant?: "default" | "secondary" | "outline" | "ghost" | "destructive" | null | undefined;
49
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
50
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
51
+ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
52
+ }
53
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
54
+ declare const badgeVariants: (props?: ({
55
+ variant?: "outline" | "neutral" | "brand" | "success" | "warning" | "danger" | "info" | null | undefined;
56
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
57
+ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
58
+ dot?: boolean;
59
+ }
60
+ declare function Badge({ className, variant, dot, children, ...props }: BadgeProps): React.JSX.Element;
61
+ declare function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
62
+ declare function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
63
+ declare function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>): React.JSX.Element;
64
+ declare function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
65
+ declare const Input: React.ForwardRefExoticComponent<React.InputHTMLAttributes<HTMLInputElement> & React.RefAttributes<HTMLInputElement>>;
66
+ declare function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>): React.JSX.Element;
67
+ declare function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
68
+ declare function TableBody({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>): React.JSX.Element;
69
+ declare function TableRow({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>): React.JSX.Element;
70
+ declare function TableHead({ className, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
71
+ declare function TableCell({ className, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>): React.JSX.Element;
72
+ interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {
73
+ }
74
+ declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLSelectElement>>;
75
+ interface TabsProps {
76
+ defaultValue?: string;
77
+ value?: string;
78
+ onValueChange?: (v: string) => void;
79
+ className?: string;
80
+ children: React.ReactNode;
81
+ }
82
+ declare function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps): React.JSX.Element;
83
+ declare function TabsList({ className, children }: {
84
+ className?: string;
85
+ children: React.ReactNode;
86
+ }): React.JSX.Element;
87
+ declare function TabsTrigger({ value, className, children, }: {
88
+ value: string;
89
+ className?: string;
90
+ children: React.ReactNode;
91
+ }): React.JSX.Element;
92
+ declare function TabsContent({ value, className, children, }: {
93
+ value: string;
94
+ className?: string;
95
+ children: React.ReactNode;
96
+ }): React.JSX.Element | null;
97
+ interface ModalProps {
98
+ open: boolean;
99
+ onClose: () => void;
100
+ title?: React.ReactNode;
101
+ children: React.ReactNode;
102
+ className?: string;
103
+ }
104
+ declare function Modal({ open, onClose, title, children, className }: ModalProps): React.JSX.Element | null;
105
+ interface SpinnerProps {
106
+ className?: string;
107
+ size?: 'sm' | 'md' | 'lg';
108
+ }
109
+ declare function Spinner({ className, size }: SpinnerProps): React.JSX.Element;
110
+ interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
111
+ variant?: 'default' | 'muted';
112
+ }
113
+ declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
114
+ interface SwitchProps {
115
+ checked?: boolean;
116
+ onCheckedChange?: (checked: boolean) => void;
117
+ disabled?: boolean;
118
+ className?: string;
119
+ 'aria-label'?: string;
120
+ }
121
+ declare function Switch({ checked, onCheckedChange, disabled, className, ...props }: SwitchProps): React.JSX.Element;
122
+ interface DateRange {
123
+ from: string;
124
+ to: string;
125
+ }
126
+ interface DateRangePickerProps {
127
+ value: DateRange;
128
+ onChange: (range: DateRange) => void;
129
+ className?: string;
130
+ disabled?: boolean;
131
+ }
132
+ /** Minimal controlled date-range picker using two native date inputs. */
133
+ declare function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps): React.JSX.Element;
134
+
135
+ export { type AppApiClient, AppApiProvider, AppContextProvider, type AppContextValue, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardHeader, CardTitle, type DateRange, DateRangePicker, type DateRangePickerProps, Input, Link, type LinkProps, Modal, type ModalProps, Select, type SelectProps, Spinner, type SpinnerProps, Switch, type SwitchProps, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, type TabsProps, TabsTrigger, cn, useAppApi, useAppContext };
package/dist/index.js ADDED
@@ -0,0 +1,323 @@
1
+ import { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import * as React from 'react';
4
+ import { createContext, useContext } from 'react';
5
+ import { cva } from 'class-variance-authority';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+
8
+ // src/cn.ts
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+ var AppContextInternalCtx = createContext(null);
13
+ var AppContextProvider = AppContextInternalCtx.Provider;
14
+ function useAppContext() {
15
+ const ctx = useContext(AppContextInternalCtx);
16
+ if (!ctx) throw new Error("useAppContext must be used inside an app page mounted by the shell");
17
+ return ctx;
18
+ }
19
+ var AppApiCtx = createContext(null);
20
+ var AppApiProvider = AppApiCtx.Provider;
21
+ function useAppApi() {
22
+ const client = useContext(AppApiCtx);
23
+ if (!client) throw new Error("useAppApi must be used inside an app page mounted by the shell");
24
+ return client;
25
+ }
26
+ var buttonVariants = cva(
27
+ "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
28
+ {
29
+ variants: {
30
+ variant: {
31
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
32
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
33
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
34
+ ghost: "hover:bg-accent hover:text-accent-foreground",
35
+ destructive: "bg-destructive text-white hover:bg-destructive/90"
36
+ },
37
+ size: {
38
+ default: "h-9 px-4 py-2",
39
+ sm: "h-8 rounded-md px-3 text-xs",
40
+ lg: "h-10 rounded-md px-6",
41
+ icon: "h-9 w-9"
42
+ }
43
+ },
44
+ defaultVariants: { variant: "default", size: "default" }
45
+ }
46
+ );
47
+ var Button = React.forwardRef(
48
+ ({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx("button", { ref, className: cn(buttonVariants({ variant, size, className })), ...props })
49
+ );
50
+ Button.displayName = "Button";
51
+ var badgeVariants = cva(
52
+ "inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap",
53
+ {
54
+ variants: {
55
+ variant: {
56
+ neutral: "border-border bg-muted text-muted-foreground",
57
+ brand: "border-primary/20 bg-primary/10 text-primary",
58
+ success: "border-status-success/25 bg-status-success/10 text-status-success",
59
+ warning: "border-status-pending/30 bg-status-pending/10 text-status-pending",
60
+ danger: "border-status-blocked/25 bg-status-blocked/10 text-status-blocked",
61
+ info: "border-status-info/25 bg-status-info/10 text-status-info",
62
+ outline: "border-border bg-transparent text-muted-foreground"
63
+ }
64
+ },
65
+ defaultVariants: { variant: "neutral" }
66
+ }
67
+ );
68
+ function Badge({ className, variant, dot, children, ...props }) {
69
+ return /* @__PURE__ */ jsxs("span", { className: cn(badgeVariants({ variant }), className), ...props, children: [
70
+ dot && /* @__PURE__ */ jsx("span", { className: "size-1.5 rounded-full bg-current" }),
71
+ children
72
+ ] });
73
+ }
74
+ function Card({ className, ...props }) {
75
+ return /* @__PURE__ */ jsx(
76
+ "div",
77
+ {
78
+ className: cn("rounded-xl border bg-card text-card-foreground shadow-sm", className),
79
+ ...props
80
+ }
81
+ );
82
+ }
83
+ function CardHeader({ className, ...props }) {
84
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 p-6", className), ...props });
85
+ }
86
+ function CardTitle({ className, ...props }) {
87
+ return /* @__PURE__ */ jsx("h3", { className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props });
88
+ }
89
+ function CardContent({ className, ...props }) {
90
+ return /* @__PURE__ */ jsx("div", { className: cn("p-6 pt-0", className), ...props });
91
+ }
92
+ var Input = React.forwardRef(
93
+ ({ className, type, ...props }, ref) => /* @__PURE__ */ jsx(
94
+ "input",
95
+ {
96
+ type,
97
+ className: cn(
98
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
99
+ className
100
+ ),
101
+ ref,
102
+ ...props
103
+ }
104
+ )
105
+ );
106
+ Input.displayName = "Input";
107
+ function Table({ className, ...props }) {
108
+ return /* @__PURE__ */ jsx("table", { className: cn("w-full text-sm", className), ...props });
109
+ }
110
+ function TableHeader({ className, ...props }) {
111
+ return /* @__PURE__ */ jsx("thead", { className: cn("[&_tr]:border-b", className), ...props });
112
+ }
113
+ function TableBody({ className, ...props }) {
114
+ return /* @__PURE__ */ jsx("tbody", { className: cn("[&_tr:last-child]:border-0", className), ...props });
115
+ }
116
+ function TableRow({ className, ...props }) {
117
+ return /* @__PURE__ */ jsx(
118
+ "tr",
119
+ {
120
+ className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className),
121
+ ...props
122
+ }
123
+ );
124
+ }
125
+ function TableHead({ className, ...props }) {
126
+ return /* @__PURE__ */ jsx(
127
+ "th",
128
+ {
129
+ className: cn("h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground", className),
130
+ ...props
131
+ }
132
+ );
133
+ }
134
+ function TableCell({ className, ...props }) {
135
+ return /* @__PURE__ */ jsx("td", { className: cn("p-4 align-middle", className), ...props });
136
+ }
137
+ var Select = React.forwardRef(
138
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
139
+ "select",
140
+ {
141
+ ref,
142
+ className: cn(
143
+ "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
144
+ className
145
+ ),
146
+ ...props,
147
+ children
148
+ }
149
+ )
150
+ );
151
+ Select.displayName = "Select";
152
+ var TabsContext = React.createContext(null);
153
+ function useTabsContext() {
154
+ const ctx = React.useContext(TabsContext);
155
+ if (!ctx) throw new Error("Tabs sub-component must be used within <Tabs>");
156
+ return ctx;
157
+ }
158
+ function Tabs({ defaultValue, value, onValueChange, className, children }) {
159
+ const [internal, setInternal] = React.useState(defaultValue ?? "");
160
+ const current = value ?? internal;
161
+ const setValue = (v) => {
162
+ setInternal(v);
163
+ onValueChange?.(v);
164
+ };
165
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value: { value: current, setValue }, children: /* @__PURE__ */ jsx("div", { className, children }) });
166
+ }
167
+ function TabsList({ className, children }) {
168
+ return /* @__PURE__ */ jsx("div", { className: cn("inline-flex items-center gap-1 rounded-lg bg-muted p-1", className), children });
169
+ }
170
+ function TabsTrigger({
171
+ value,
172
+ className,
173
+ children
174
+ }) {
175
+ const { value: current, setValue } = useTabsContext();
176
+ const active = current === value;
177
+ return /* @__PURE__ */ jsx(
178
+ "button",
179
+ {
180
+ type: "button",
181
+ onClick: () => setValue(value),
182
+ className: cn(
183
+ "rounded-md px-3 py-1.5 text-sm font-medium transition-colors",
184
+ active ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground",
185
+ className
186
+ ),
187
+ children
188
+ }
189
+ );
190
+ }
191
+ function TabsContent({
192
+ value,
193
+ className,
194
+ children
195
+ }) {
196
+ const { value: current } = useTabsContext();
197
+ if (current !== value) return null;
198
+ return /* @__PURE__ */ jsx("div", { className, children });
199
+ }
200
+ function Modal({ open, onClose, title, children, className }) {
201
+ if (!open) return null;
202
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
203
+ /* @__PURE__ */ jsx(
204
+ "button",
205
+ {
206
+ type: "button",
207
+ "aria-label": "Close",
208
+ className: "absolute inset-0 cursor-default bg-foreground/40",
209
+ onClick: onClose
210
+ }
211
+ ),
212
+ /* @__PURE__ */ jsxs(
213
+ "div",
214
+ {
215
+ role: "dialog",
216
+ "aria-modal": true,
217
+ className: cn("relative z-10 w-full max-w-md rounded-xl border bg-card p-5 shadow-lg", className),
218
+ children: [
219
+ title && /* @__PURE__ */ jsx("h2", { className: "mb-3 text-base font-semibold", children: title }),
220
+ children
221
+ ]
222
+ }
223
+ )
224
+ ] });
225
+ }
226
+ var spinnerSizes = { sm: "size-4", md: "size-6", lg: "size-8" };
227
+ function Spinner({ className, size = "md" }) {
228
+ return /* @__PURE__ */ jsxs(
229
+ "svg",
230
+ {
231
+ className: cn("animate-spin text-muted-foreground", spinnerSizes[size], className),
232
+ xmlns: "http://www.w3.org/2000/svg",
233
+ fill: "none",
234
+ viewBox: "0 0 24 24",
235
+ "aria-label": "Loading",
236
+ role: "status",
237
+ children: [
238
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
239
+ /* @__PURE__ */ jsx(
240
+ "path",
241
+ {
242
+ className: "opacity-75",
243
+ fill: "currentColor",
244
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
245
+ }
246
+ )
247
+ ]
248
+ }
249
+ );
250
+ }
251
+ var Link = React.forwardRef(
252
+ ({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ jsx(
253
+ "a",
254
+ {
255
+ ref,
256
+ className: cn(
257
+ "underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
258
+ variant === "default" ? "text-primary" : "text-muted-foreground",
259
+ className
260
+ ),
261
+ ...props
262
+ }
263
+ )
264
+ );
265
+ Link.displayName = "Link";
266
+ function Switch({ checked = false, onCheckedChange, disabled, className, ...props }) {
267
+ return /* @__PURE__ */ jsx(
268
+ "button",
269
+ {
270
+ type: "button",
271
+ role: "switch",
272
+ "aria-checked": checked,
273
+ disabled,
274
+ onClick: () => onCheckedChange?.(!checked),
275
+ className: cn(
276
+ "relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
277
+ checked ? "bg-primary" : "bg-input",
278
+ className
279
+ ),
280
+ ...props,
281
+ children: /* @__PURE__ */ jsx(
282
+ "span",
283
+ {
284
+ className: cn(
285
+ "inline-block size-4 transform rounded-full bg-white shadow transition-transform",
286
+ checked ? "translate-x-4" : "translate-x-0.5"
287
+ )
288
+ }
289
+ )
290
+ }
291
+ );
292
+ }
293
+ function DateRangePicker({ value, onChange, className, disabled }) {
294
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
295
+ /* @__PURE__ */ jsx(
296
+ "input",
297
+ {
298
+ type: "date",
299
+ disabled,
300
+ value: value.from,
301
+ max: value.to || void 0,
302
+ onChange: (e) => onChange({ ...value, from: e.target.value }),
303
+ className: "flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "\u2192" }),
307
+ /* @__PURE__ */ jsx(
308
+ "input",
309
+ {
310
+ type: "date",
311
+ disabled,
312
+ value: value.to,
313
+ min: value.from || void 0,
314
+ onChange: (e) => onChange({ ...value, to: e.target.value }),
315
+ className: "flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
316
+ }
317
+ )
318
+ ] });
319
+ }
320
+
321
+ export { AppApiProvider, AppContextProvider, Badge, Button, Card, CardContent, CardHeader, CardTitle, DateRangePicker, Input, Link, Modal, Select, Spinner, Switch, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, cn, useAppApi, useAppContext };
322
+ //# sourceMappingURL=index.js.map
323
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cn.ts","../src/hooks.ts","../src/components.tsx"],"names":[],"mappings":";;;;;;;;AAGO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACqBA,IAAM,qBAAA,GAAwB,cAAsC,IAAI,CAAA;AAEjE,IAAM,qBAAqB,qBAAA,CAAsB;AAGjD,SAAS,aAAA,GAAiC;AAC/C,EAAA,MAAM,GAAA,GAAM,WAAW,qBAAqB,CAAA;AAC5C,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,oEAAoE,CAAA;AAC9F,EAAA,OAAO,GAAA;AACT;AAkBA,IAAM,SAAA,GAAY,cAAmC,IAAI,CAAA;AAElD,IAAM,iBAAiB,SAAA,CAAU;AAMjC,SAAS,SAAA,GAA0B;AACxC,EAAA,MAAM,MAAA,GAAS,WAAW,SAAS,CAAA;AACnC,EAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAC7F,EAAA,OAAO,MAAA;AACT;AC3CA,IAAM,cAAA,GAAiB,GAAA;AAAA,EACrB,0PAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,wDAAA;AAAA,QACT,SAAA,EAAW,8DAAA;AAAA,QACX,OAAA,EAAS,gFAAA;AAAA,QACT,KAAA,EAAO,8CAAA;AAAA,QACP,WAAA,EAAa;AAAA,OACf;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,eAAA;AAAA,QACT,EAAA,EAAI,6BAAA;AAAA,QACJ,EAAA,EAAI,sBAAA;AAAA,QACJ,IAAA,EAAM;AAAA;AACR,KACF;AAAA,IACA,eAAA,EAAiB,EAAE,OAAA,EAAS,SAAA,EAAW,MAAM,SAAA;AAAU;AAE3D,CAAA;AAMO,IAAM,MAAA,GAAe,KAAA,CAAA,UAAA;AAAA,EAC1B,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,MAAM,GAAG,KAAA,EAAM,EAAG,GAAA,qBACvC,GAAA,CAAC,QAAA,EAAA,EAAO,KAAU,SAAA,EAAW,EAAA,CAAG,cAAA,CAAe,EAAE,OAAA,EAAS,IAAA,EAAM,WAAW,CAAC,CAAA,EAAI,GAAG,KAAA,EAAO;AAE9F;AACA,MAAA,CAAO,WAAA,GAAc,QAAA;AAMrB,IAAM,aAAA,GAAgB,GAAA;AAAA,EACpB,wGAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,8CAAA;AAAA,QACT,KAAA,EAAO,8CAAA;AAAA,QACP,OAAA,EAAS,mEAAA;AAAA,QACT,OAAA,EAAS,mEAAA;AAAA,QACT,MAAA,EAAQ,mEAAA;AAAA,QACR,IAAA,EAAM,0DAAA;AAAA,QACN,OAAA,EAAS;AAAA;AACX,KACF;AAAA,IACA,eAAA,EAAiB,EAAE,OAAA,EAAS,SAAA;AAAU;AAE1C,CAAA;AAQO,SAAS,KAAA,CAAM,EAAE,SAAA,EAAW,OAAA,EAAS,KAAK,QAAA,EAAU,GAAG,OAAM,EAAe;AACjF,EAAA,uBACE,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,EAAA,CAAG,aAAA,CAAc,EAAE,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAI,GAAG,KAAA,EAC7D,QAAA,EAAA;AAAA,IAAA,GAAA,oBAAO,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCAAA,EAAmC,CAAA;AAAA,IAC1D;AAAA,GAAA,EACH,CAAA;AAEJ;AAMO,SAAS,IAAA,CAAK,EAAE,SAAA,EAAW,GAAG,OAAM,EAAyC;AAClF,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,0DAAA,EAA4D,SAAS,CAAA;AAAA,MAClF,GAAG;AAAA;AAAA,GACN;AAEJ;AAEO,SAAS,UAAA,CAAW,EAAE,SAAA,EAAW,GAAG,OAAM,EAAyC;AACxF,EAAA,uBAAO,GAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,iCAAiC,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACpF;AAEO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAW,GAAG,OAAM,EAA6C;AAC3F,EAAA,uBAAO,GAAA,CAAC,QAAG,SAAA,EAAW,EAAA,CAAG,qDAAqD,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACvG;AAEO,SAAS,WAAA,CAAY,EAAE,SAAA,EAAW,GAAG,OAAM,EAAyC;AACzF,EAAA,uBAAO,GAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,YAAY,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AAC/D;AAMO,IAAM,KAAA,GAAc,KAAA,CAAA,UAAA;AAAA,EACzB,CAAC,EAAE,SAAA,EAAW,MAAM,GAAG,KAAA,IAAS,GAAA,qBAC9B,GAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,uUAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,GAAA;AAAA,MACC,GAAG;AAAA;AAAA;AAGV;AACA,KAAA,CAAM,WAAA,GAAc,OAAA;AAMb,SAAS,KAAA,CAAM,EAAE,SAAA,EAAW,GAAG,OAAM,EAA2C;AACrF,EAAA,uBAAO,GAAA,CAAC,WAAM,SAAA,EAAW,EAAA,CAAG,kBAAkB,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACvE;AAEO,SAAS,WAAA,CAAY,EAAE,SAAA,EAAW,GAAG,OAAM,EAAkD;AAClG,EAAA,uBAAO,GAAA,CAAC,WAAM,SAAA,EAAW,EAAA,CAAG,mBAAmB,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACxE;AAEO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAW,GAAG,OAAM,EAAkD;AAChG,EAAA,uBAAO,GAAA,CAAC,WAAM,SAAA,EAAW,EAAA,CAAG,8BAA8B,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACnF;AAEO,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,GAAG,OAAM,EAA8C;AAC3F,EAAA,uBACE,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,6EAAA,EAA+E,SAAS,CAAA;AAAA,MACrG,GAAG;AAAA;AAAA,GACN;AAEJ;AAEO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAW,GAAG,OAAM,EAAiD;AAC/F,EAAA,uBACE,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,4EAAA,EAA8E,SAAS,CAAA;AAAA,MACpG,GAAG;AAAA;AAAA,GACN;AAEJ;AAEO,SAAS,SAAA,CAAU,EAAE,SAAA,EAAW,GAAG,OAAM,EAAiD;AAC/F,EAAA,uBAAO,GAAA,CAAC,QAAG,SAAA,EAAW,EAAA,CAAG,oBAAoB,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACtE;AAQO,IAAM,MAAA,GAAe,KAAA,CAAA,UAAA;AAAA,EAC1B,CAAC,EAAE,SAAA,EAAW,UAAU,GAAG,KAAA,IAAS,GAAA,qBAClC,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,qOAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEH;AAAA;AAAA;AAGP;AACA,MAAA,CAAO,WAAA,GAAc,QAAA;AAWrB,IAAM,WAAA,GAAoB,oBAAuC,IAAI,CAAA;AAErE,SAAS,cAAA,GAAmC;AAC1C,EAAA,MAAM,GAAA,GAAY,iBAAW,WAAW,CAAA;AACxC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,+CAA+C,CAAA;AACzE,EAAA,OAAO,GAAA;AACT;AAUO,SAAS,KAAK,EAAE,YAAA,EAAc,OAAO,aAAA,EAAe,SAAA,EAAW,UAAS,EAAc;AAC3F,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,KAAA,CAAA,QAAA,CAAS,gBAAgB,EAAE,CAAA;AACjE,EAAA,MAAM,UAAU,KAAA,IAAS,QAAA;AACzB,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAc;AAC9B,IAAA,WAAA,CAAY,CAAC,CAAA;AACb,IAAA,aAAA,GAAgB,CAAC,CAAA;AAAA,EACnB,CAAA;AACA,EAAA,uBACE,GAAA,CAAC,WAAA,CAAY,QAAA,EAAZ,EAAqB,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAS,EACtD,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAuB,UAAS,CAAA,EACvC,CAAA;AAEJ;AAEO,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,QAAA,EAAS,EAAsD;AACnG,EAAA,2BACG,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,wDAAA,EAA0D,SAAS,GACnF,QAAA,EACH,CAAA;AAEJ;AAEO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,KAAa,cAAA,EAAe;AACpD,EAAA,MAAM,SAAS,OAAA,KAAY,KAAA;AAC3B,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,OAAA,EAAS,MAAM,QAAA,CAAS,KAAK,CAAA;AAAA,MAC7B,SAAA,EAAW,EAAA;AAAA,QACT,8DAAA;AAAA,QACA,SAAS,mCAAA,GAAsC,6CAAA;AAAA,QAC/C;AAAA,OACF;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAEO,SAAS,WAAA,CAAY;AAAA,EAC1B,KAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAIG;AACD,EAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAQ,GAAI,cAAA,EAAe;AAC1C,EAAA,IAAI,OAAA,KAAY,OAAO,OAAO,IAAA;AAC9B,EAAA,uBAAO,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAuB,QAAA,EAAS,CAAA;AAC9C;AAcO,SAAS,MAAM,EAAE,IAAA,EAAM,SAAS,KAAA,EAAO,QAAA,EAAU,WAAU,EAAe;AAC/E,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yDAAA,EACb,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAW,OAAA;AAAA,QACX,SAAA,EAAU,kDAAA;AAAA,QACV,OAAA,EAAS;AAAA;AAAA,KACX;AAAA,oBACA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,YAAA,EAAU,IAAA;AAAA,QACV,SAAA,EAAW,EAAA,CAAG,uEAAA,EAAyE,SAAS,CAAA;AAAA,QAE/F,QAAA,EAAA;AAAA,UAAA,KAAA,oBAAS,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,8BAAA,EAAgC,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UAC7D;AAAA;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAEJ;AAWA,IAAM,eAAe,EAAE,EAAA,EAAI,UAAU,EAAA,EAAI,QAAA,EAAU,IAAI,QAAA,EAAS;AAEzD,SAAS,OAAA,CAAQ,EAAE,SAAA,EAAW,IAAA,GAAO,MAAK,EAAiB;AAChE,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAW,EAAA,CAAG,oCAAA,EAAsC,YAAA,CAAa,IAAI,GAAG,SAAS,CAAA;AAAA,MACjF,KAAA,EAAM,4BAAA;AAAA,MACN,IAAA,EAAK,MAAA;AAAA,MACL,OAAA,EAAQ,WAAA;AAAA,MACR,YAAA,EAAW,SAAA;AAAA,MACX,IAAA,EAAK,QAAA;AAAA,MAEL,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,YAAA,EAAa,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,CAAA,EAAE,IAAA,EAAK,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,CAAA;AAAA,wBAC5F,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,YAAA;AAAA,YACV,IAAA,EAAK,cAAA;AAAA,YACL,CAAA,EAAE;AAAA;AAAA;AACJ;AAAA;AAAA,GACF;AAEJ;AAUO,IAAM,IAAA,GAAa,KAAA,CAAA,UAAA;AAAA,EACxB,CAAC,EAAE,SAAA,EAAW,OAAA,GAAU,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC7C,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,4GAAA;AAAA,QACA,OAAA,KAAY,YAAY,cAAA,GAAiB,uBAAA;AAAA,QACzC;AAAA,OACF;AAAA,MACC,GAAG;AAAA;AAAA;AAGV;AACA,IAAA,CAAK,WAAA,GAAc,MAAA;AAcZ,SAAS,MAAA,CAAO,EAAE,OAAA,GAAU,KAAA,EAAO,iBAAiB,QAAA,EAAU,SAAA,EAAW,GAAG,KAAA,EAAM,EAAgB;AACvG,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAK,QAAA;AAAA,MACL,IAAA,EAAK,QAAA;AAAA,MACL,cAAA,EAAc,OAAA;AAAA,MACd,QAAA;AAAA,MACA,OAAA,EAAS,MAAM,eAAA,GAAkB,CAAC,OAAO,CAAA;AAAA,MACzC,SAAA,EAAW,EAAA;AAAA,QACT,0NAAA;AAAA,QACA,UAAU,YAAA,GAAe,UAAA;AAAA,QACzB;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,EAAA;AAAA,YACT,iFAAA;AAAA,YACA,UAAU,eAAA,GAAkB;AAAA;AAC9B;AAAA;AACF;AAAA,GACF;AAEJ;AAmBO,SAAS,gBAAgB,EAAE,KAAA,EAAO,QAAA,EAAU,SAAA,EAAW,UAAS,EAAyB;AAC9F,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,yBAAA,EAA2B,SAAS,CAAA,EACrD,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,MAAA;AAAA,QACL,QAAA;AAAA,QACA,OAAO,KAAA,CAAM,IAAA;AAAA,QACb,GAAA,EAAK,MAAM,EAAA,IAAM,MAAA;AAAA,QACjB,QAAA,EAAU,CAAC,CAAA,KAAM,QAAA,CAAS,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,CAAA,CAAE,MAAA,CAAO,KAAA,EAAO,CAAA;AAAA,QAC5D,SAAA,EAAU;AAAA;AAAA,KACZ;AAAA,oBACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+BAAA,EAAgC,QAAA,EAAA,QAAA,EAAC,CAAA;AAAA,oBACjD,GAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,MAAA;AAAA,QACL,QAAA;AAAA,QACA,OAAO,KAAA,CAAM,EAAA;AAAA,QACb,GAAA,EAAK,MAAM,IAAA,IAAQ,MAAA;AAAA,QACnB,QAAA,EAAU,CAAC,CAAA,KAAM,QAAA,CAAS,EAAE,GAAG,KAAA,EAAO,EAAA,EAAI,CAAA,CAAE,MAAA,CAAO,KAAA,EAAO,CAAA;AAAA,QAC1D,SAAA,EAAU;AAAA;AAAA;AACZ,GAAA,EACF,CAAA;AAEJ","file":"index.js","sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * Runtime hooks provided by the shell via @apotech-os/ui-sdk.\n *\n * These hooks are implemented by the shell and injected at runtime via the\n * import map. App pages call them without knowing the shell internals.\n *\n * The default implementations throw if called outside of the shell context\n * (which should never happen in production — the shell always provides them\n * via the import map before mounting an app page).\n */\n\nimport { useContext, createContext } from 'react';\n\n// ---------------------------------------------------------------------------\n// AppContext\n// ---------------------------------------------------------------------------\n\nexport interface AppContextValue {\n /** The slug of the installed app owning this page. */\n appSlug: string;\n /** The page path within the app (e.g. 'attribution'). */\n pagePath: string;\n /** The active space id, when applicable. */\n spaceId?: string;\n}\n\nconst AppContextInternalCtx = createContext<AppContextValue | null>(null);\n\nexport const AppContextProvider = AppContextInternalCtx.Provider;\n\n/** Returns context info for the current app page (appSlug, pagePath, spaceId). */\nexport function useAppContext(): AppContextValue {\n const ctx = useContext(AppContextInternalCtx);\n if (!ctx) throw new Error('useAppContext must be used inside an app page mounted by the shell');\n return ctx;\n}\n\n// ---------------------------------------------------------------------------\n// AppApi\n// ---------------------------------------------------------------------------\n\nexport interface AppApiClient {\n /**\n * Perform a GET request to a platform-data endpoint.\n * The session cookie is forwarded automatically (same-origin, withCredentials).\n */\n get<T>(path: string, params?: Record<string, string>): Promise<T>;\n /**\n * Perform a POST request to a platform-data endpoint.\n */\n post<T>(path: string, body?: unknown): Promise<T>;\n}\n\nconst AppApiCtx = createContext<AppApiClient | null>(null);\n\nexport const AppApiProvider = AppApiCtx.Provider;\n\n/**\n * Returns an API client scoped to the current user session.\n * Requests go to /api/data/* with the session cookie (RBAC applies server-side).\n */\nexport function useAppApi(): AppApiClient {\n const client = useContext(AppApiCtx);\n if (!client) throw new Error('useAppApi must be used inside an app page mounted by the shell');\n return client;\n}\n","/**\n * Design system components exported by @apotech-os/ui-sdk.\n *\n * These are minimal self-contained copies of the shell's component library.\n * They use the same Tailwind utility classes as the shell — Tailwind classes\n * are plain strings and work without any build step when the shell's stylesheet\n * is loaded (which it is, since these pages run inside the shell).\n *\n * Strategy note:\n * - Not imported from apps/web (would create a circular dep pkg → app).\n * - Copied/adapted here to keep the SDK self-contained and publishable.\n * - The exhaustive component inventory is tracked in #75.\n */\n\nimport { type VariantProps, cva } from 'class-variance-authority';\nimport * as React from 'react';\nimport { cn } from './cn';\n\n// ---------------------------------------------------------------------------\n// Button\n// ---------------------------------------------------------------------------\n\nconst buttonVariants = cva(\n 'inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n destructive: 'bg-destructive text-white hover:bg-destructive/90',\n },\n size: {\n default: 'h-9 px-4 py-2',\n sm: 'h-8 rounded-md px-3 text-xs',\n lg: 'h-10 rounded-md px-6',\n icon: 'h-9 w-9',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, ...props }, ref) => (\n <button ref={ref} className={cn(buttonVariants({ variant, size, className }))} {...props} />\n ),\n);\nButton.displayName = 'Button';\n\n// ---------------------------------------------------------------------------\n// Badge\n// ---------------------------------------------------------------------------\n\nconst badgeVariants = cva(\n 'inline-flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-xs font-medium whitespace-nowrap',\n {\n variants: {\n variant: {\n neutral: 'border-border bg-muted text-muted-foreground',\n brand: 'border-primary/20 bg-primary/10 text-primary',\n success: 'border-status-success/25 bg-status-success/10 text-status-success',\n warning: 'border-status-pending/30 bg-status-pending/10 text-status-pending',\n danger: 'border-status-blocked/25 bg-status-blocked/10 text-status-blocked',\n info: 'border-status-info/25 bg-status-info/10 text-status-info',\n outline: 'border-border bg-transparent text-muted-foreground',\n },\n },\n defaultVariants: { variant: 'neutral' },\n },\n);\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof badgeVariants> {\n dot?: boolean;\n}\n\nexport function Badge({ className, variant, dot, children, ...props }: BadgeProps) {\n return (\n <span className={cn(badgeVariants({ variant }), className)} {...props}>\n {dot && <span className=\"size-1.5 rounded-full bg-current\" />}\n {children}\n </span>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Card\n// ---------------------------------------------------------------------------\n\nexport function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('rounded-xl border bg-card text-card-foreground shadow-sm', className)}\n {...props}\n />\n );\n}\n\nexport function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />;\n}\n\nexport function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {\n return <h3 className={cn('text-lg font-semibold leading-none tracking-tight', className)} {...props} />;\n}\n\nexport function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn('p-6 pt-0', className)} {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Input\n// ---------------------------------------------------------------------------\n\nexport const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(\n ({ className, type, ...props }, ref) => (\n <input\n type={type}\n className={cn(\n 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n ref={ref}\n {...props}\n />\n ),\n);\nInput.displayName = 'Input';\n\n// ---------------------------------------------------------------------------\n// Table\n// ---------------------------------------------------------------------------\n\nexport function Table({ className, ...props }: React.HTMLAttributes<HTMLTableElement>) {\n return <table className={cn('w-full text-sm', className)} {...props} />;\n}\n\nexport function TableHeader({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) {\n return <thead className={cn('[&_tr]:border-b', className)} {...props} />;\n}\n\nexport function TableBody({ className, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) {\n return <tbody className={cn('[&_tr:last-child]:border-0', className)} {...props} />;\n}\n\nexport function TableRow({ className, ...props }: React.HTMLAttributes<HTMLTableRowElement>) {\n return (\n <tr\n className={cn('border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted', className)}\n {...props}\n />\n );\n}\n\nexport function TableHead({ className, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>) {\n return (\n <th\n className={cn('h-10 px-4 text-left align-middle text-xs font-medium text-muted-foreground', className)}\n {...props}\n />\n );\n}\n\nexport function TableCell({ className, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>) {\n return <td className={cn('p-4 align-middle', className)} {...props} />;\n}\n\n// ---------------------------------------------------------------------------\n// Select\n// ---------------------------------------------------------------------------\n\nexport interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> {}\n\nexport const Select = React.forwardRef<HTMLSelectElement, SelectProps>(\n ({ className, children, ...props }, ref) => (\n <select\n ref={ref}\n className={cn(\n 'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {children}\n </select>\n ),\n);\nSelect.displayName = 'Select';\n\n// ---------------------------------------------------------------------------\n// Tabs\n// ---------------------------------------------------------------------------\n\ninterface TabsContextValue {\n value: string;\n setValue: (v: string) => void;\n}\n\nconst TabsContext = React.createContext<TabsContextValue | null>(null);\n\nfunction useTabsContext(): TabsContextValue {\n const ctx = React.useContext(TabsContext);\n if (!ctx) throw new Error('Tabs sub-component must be used within <Tabs>');\n return ctx;\n}\n\nexport interface TabsProps {\n defaultValue?: string;\n value?: string;\n onValueChange?: (v: string) => void;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function Tabs({ defaultValue, value, onValueChange, className, children }: TabsProps) {\n const [internal, setInternal] = React.useState(defaultValue ?? '');\n const current = value ?? internal;\n const setValue = (v: string) => {\n setInternal(v);\n onValueChange?.(v);\n };\n return (\n <TabsContext.Provider value={{ value: current, setValue }}>\n <div className={className}>{children}</div>\n </TabsContext.Provider>\n );\n}\n\nexport function TabsList({ className, children }: { className?: string; children: React.ReactNode }) {\n return (\n <div className={cn('inline-flex items-center gap-1 rounded-lg bg-muted p-1', className)}>\n {children}\n </div>\n );\n}\n\nexport function TabsTrigger({\n value,\n className,\n children,\n}: {\n value: string;\n className?: string;\n children: React.ReactNode;\n}) {\n const { value: current, setValue } = useTabsContext();\n const active = current === value;\n return (\n <button\n type=\"button\"\n onClick={() => setValue(value)}\n className={cn(\n 'rounded-md px-3 py-1.5 text-sm font-medium transition-colors',\n active ? 'bg-card text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n className,\n )}\n >\n {children}\n </button>\n );\n}\n\nexport function TabsContent({\n value,\n className,\n children,\n}: {\n value: string;\n className?: string;\n children: React.ReactNode;\n}) {\n const { value: current } = useTabsContext();\n if (current !== value) return null;\n return <div className={className}>{children}</div>;\n}\n\n// ---------------------------------------------------------------------------\n// Modal (controlled, no Radix)\n// ---------------------------------------------------------------------------\n\nexport interface ModalProps {\n open: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n children: React.ReactNode;\n className?: string;\n}\n\nexport function Modal({ open, onClose, title, children, className }: ModalProps) {\n if (!open) return null;\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <button\n type=\"button\"\n aria-label=\"Close\"\n className=\"absolute inset-0 cursor-default bg-foreground/40\"\n onClick={onClose}\n />\n <div\n role=\"dialog\"\n aria-modal\n className={cn('relative z-10 w-full max-w-md rounded-xl border bg-card p-5 shadow-lg', className)}\n >\n {title && <h2 className=\"mb-3 text-base font-semibold\">{title}</h2>}\n {children}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Spinner\n// ---------------------------------------------------------------------------\n\nexport interface SpinnerProps {\n className?: string;\n size?: 'sm' | 'md' | 'lg';\n}\n\nconst spinnerSizes = { sm: 'size-4', md: 'size-6', lg: 'size-8' };\n\nexport function Spinner({ className, size = 'md' }: SpinnerProps) {\n return (\n <svg\n className={cn('animate-spin text-muted-foreground', spinnerSizes[size], className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-label=\"Loading\"\n role=\"status\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Link\n// ---------------------------------------------------------------------------\n\nexport interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\n variant?: 'default' | 'muted';\n}\n\nexport const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(\n ({ className, variant = 'default', ...props }, ref) => (\n <a\n ref={ref}\n className={cn(\n 'underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',\n variant === 'default' ? 'text-primary' : 'text-muted-foreground',\n className,\n )}\n {...props}\n />\n ),\n);\nLink.displayName = 'Link';\n\n// ---------------------------------------------------------------------------\n// Switch\n// ---------------------------------------------------------------------------\n\nexport interface SwitchProps {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n 'aria-label'?: string;\n}\n\nexport function Switch({ checked = false, onCheckedChange, disabled, className, ...props }: SwitchProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n disabled={disabled}\n onClick={() => onCheckedChange?.(!checked)}\n className={cn(\n 'relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',\n checked ? 'bg-primary' : 'bg-input',\n className,\n )}\n {...props}\n >\n <span\n className={cn(\n 'inline-block size-4 transform rounded-full bg-white shadow transition-transform',\n checked ? 'translate-x-4' : 'translate-x-0.5',\n )}\n />\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// DateRangePicker\n// ---------------------------------------------------------------------------\n\nexport interface DateRange {\n from: string;\n to: string;\n}\n\nexport interface DateRangePickerProps {\n value: DateRange;\n onChange: (range: DateRange) => void;\n className?: string;\n disabled?: boolean;\n}\n\n/** Minimal controlled date-range picker using two native date inputs. */\nexport function DateRangePicker({ value, onChange, className, disabled }: DateRangePickerProps) {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n <input\n type=\"date\"\n disabled={disabled}\n value={value.from}\n max={value.to || undefined}\n onChange={(e) => onChange({ ...value, from: e.target.value })}\n className=\"flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n <span className=\"text-muted-foreground text-sm\">→</span>\n <input\n type=\"date\"\n disabled={disabled}\n value={value.to}\n min={value.from || undefined}\n onChange={(e) => onChange({ ...value, to: e.target.value })}\n className=\"flex h-9 rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@apotech-os/ui-sdk",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/apotech-studio/wopilo-os.git"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=18",
32
+ "react-dom": ">=18"
33
+ },
34
+ "dependencies": {
35
+ "class-variance-authority": "^0.7.1",
36
+ "clsx": "^2.1.1",
37
+ "tailwind-merge": "^3.3.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/react": "^19.2.17",
41
+ "@types/react-dom": "^19.2.3",
42
+ "tsup": "^8.5.0",
43
+ "typescript": "~5.9.3",
44
+ "vitest": "^4.1.9"
45
+ },
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "dev": "tsup --watch",
49
+ "typecheck": "tsc --noEmit",
50
+ "test": "vitest run"
51
+ }
52
+ }