@hexdspace/react 0.1.10 → 0.1.11
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/css/component.css +56 -21
- package/dist/index.d.ts +162 -4
- package/dist/index.js +472 -49
- package/package.json +3 -1
package/dist/css/component.css
CHANGED
|
@@ -81,20 +81,6 @@
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
@layer components {
|
|
84
|
-
.card {
|
|
85
|
-
background: var(--surface-2);
|
|
86
|
-
border: 1px solid color-mix(in oklab, var(--border), transparent 80%);
|
|
87
|
-
border-radius: var(--radius-card);
|
|
88
|
-
box-shadow: var(--shadow-elevated);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.popover {
|
|
92
|
-
background: var(--surface-3);
|
|
93
|
-
border: 1px solid color-mix(in oklab, var(--border), transparent 40%);
|
|
94
|
-
border-radius: var(--radius-card);
|
|
95
|
-
box-shadow: var(--shadow-popover);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
84
|
.shell {
|
|
99
85
|
background: var(--surface-1);
|
|
100
86
|
border-radius: var(--radius-shell);
|
|
@@ -107,10 +93,11 @@
|
|
|
107
93
|
box-shadow: var(--shadow-elevated);
|
|
108
94
|
}
|
|
109
95
|
|
|
110
|
-
.
|
|
111
|
-
background: var(--surface-
|
|
96
|
+
.card {
|
|
97
|
+
background: var(--surface-2);
|
|
98
|
+
border: 1px solid color-mix(in oklab, var(--border), transparent 80%);
|
|
112
99
|
border-radius: var(--radius-card);
|
|
113
|
-
box-shadow:
|
|
100
|
+
box-shadow: var(--shadow-elevated);
|
|
114
101
|
}
|
|
115
102
|
|
|
116
103
|
.chip {
|
|
@@ -156,10 +143,58 @@
|
|
|
156
143
|
}
|
|
157
144
|
}
|
|
158
145
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
146
|
+
@keyframes dialog-overlay-in {
|
|
147
|
+
from {
|
|
148
|
+
opacity: 0;
|
|
149
|
+
}
|
|
150
|
+
to {
|
|
151
|
+
opacity: 1;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@keyframes dialog-overlay-out {
|
|
156
|
+
from {
|
|
157
|
+
opacity: 1;
|
|
158
|
+
}
|
|
159
|
+
to {
|
|
160
|
+
opacity: 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@keyframes dialog-fade-in {
|
|
165
|
+
from {
|
|
166
|
+
opacity: 0;
|
|
167
|
+
}
|
|
168
|
+
to {
|
|
169
|
+
opacity: 1;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@keyframes dialog-fade-out {
|
|
174
|
+
from {
|
|
175
|
+
opacity: 1;
|
|
176
|
+
}
|
|
177
|
+
to {
|
|
178
|
+
opacity: 0;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@keyframes dialog-surface-in {
|
|
183
|
+
from {
|
|
184
|
+
transform: translateY(0.75rem);
|
|
185
|
+
}
|
|
186
|
+
to {
|
|
187
|
+
transform: translateY(0);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@keyframes dialog-surface-out {
|
|
192
|
+
from {
|
|
193
|
+
transform: translateY(0);
|
|
194
|
+
}
|
|
195
|
+
to {
|
|
196
|
+
transform: translateY(0.75rem);
|
|
197
|
+
}
|
|
163
198
|
}
|
|
164
199
|
|
|
165
200
|
:root .prose code {
|
package/dist/index.d.ts
CHANGED
|
@@ -155,8 +155,8 @@ type UIFail = ResultError<string> & {
|
|
|
155
155
|
};
|
|
156
156
|
type UIResult<T> = UIOk<T> | UIFail;
|
|
157
157
|
declare const ui: {
|
|
158
|
-
success: <T>(value: T, ...effects: Instruction[]) =>
|
|
159
|
-
failure: (error: string, ...effects: Instruction[]) =>
|
|
158
|
+
success: <T>(value: T, ...effects: Instruction[]) => UIOk<T>;
|
|
159
|
+
failure: (error: string, ...effects: Instruction[]) => UIFail;
|
|
160
160
|
};
|
|
161
161
|
|
|
162
162
|
type OptimisticSnapshot = {
|
|
@@ -409,6 +409,163 @@ interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
|
409
409
|
}
|
|
410
410
|
declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
411
411
|
|
|
412
|
+
type ConfirmPayload = {
|
|
413
|
+
title: string;
|
|
414
|
+
message?: string;
|
|
415
|
+
confirmText?: string;
|
|
416
|
+
cancelText?: string;
|
|
417
|
+
variant?: React__default.ComponentProps<typeof Button>['variant'];
|
|
418
|
+
danger?: boolean;
|
|
419
|
+
children?: React__default.ReactNode;
|
|
420
|
+
};
|
|
421
|
+
interface ConfirmDialogProps {
|
|
422
|
+
id: string;
|
|
423
|
+
payload?: ConfirmPayload;
|
|
424
|
+
onResolve?: (result?: unknown) => void;
|
|
425
|
+
}
|
|
426
|
+
declare const ConfirmDialog: React__default.FC<ConfirmDialogProps>;
|
|
427
|
+
|
|
428
|
+
interface CustomDialogPayload {
|
|
429
|
+
children?: React__default.ReactNode;
|
|
430
|
+
}
|
|
431
|
+
interface CustomDialogProps {
|
|
432
|
+
id: string;
|
|
433
|
+
payload?: CustomDialogPayload;
|
|
434
|
+
onResolve?: (result?: unknown) => void;
|
|
435
|
+
}
|
|
436
|
+
declare const CustomDialog: React__default.FC<CustomDialogProps>;
|
|
437
|
+
|
|
438
|
+
interface InfoPayload {
|
|
439
|
+
title: string;
|
|
440
|
+
children?: React__default.ReactNode;
|
|
441
|
+
confirmText?: string;
|
|
442
|
+
}
|
|
443
|
+
interface InfoDialogProps {
|
|
444
|
+
id: string;
|
|
445
|
+
payload?: InfoPayload;
|
|
446
|
+
onResolve?: (result?: unknown) => void;
|
|
447
|
+
}
|
|
448
|
+
declare const InfoDialog: React__default.FC<InfoDialogProps>;
|
|
449
|
+
|
|
450
|
+
declare function registerDefaultDialogs(): void;
|
|
451
|
+
type DefaultDialogPayloads = {
|
|
452
|
+
custom: CustomDialogPayload;
|
|
453
|
+
confirm: ConfirmPayload;
|
|
454
|
+
info: InfoPayload;
|
|
455
|
+
};
|
|
456
|
+
type DefaultDialogTemplateKey = keyof DefaultDialogPayloads;
|
|
457
|
+
declare const DefaultDialogTemplateKeys: ["custom", "confirm", "info"];
|
|
458
|
+
|
|
459
|
+
type DialogTemplate<TPayload = unknown> = React__default.ComponentType<{
|
|
460
|
+
id: string;
|
|
461
|
+
payload?: TPayload;
|
|
462
|
+
onResolve?: (result?: unknown) => void;
|
|
463
|
+
}>;
|
|
464
|
+
declare function registerDialogTemplate<TPayload>(key: string, component: DialogTemplate<TPayload>): void;
|
|
465
|
+
declare function unregisterDialogTemplate(key: string): void;
|
|
466
|
+
declare function getDialogTemplate<K extends DefaultDialogTemplateKey>(key: K): DialogTemplate<DefaultDialogPayloads[K]> | undefined;
|
|
467
|
+
declare function getDialogTemplate<TPayload = unknown>(key: string): DialogTemplate<TPayload> | undefined;
|
|
468
|
+
|
|
469
|
+
declare const DialogHost: React.FC;
|
|
470
|
+
|
|
471
|
+
interface DialogOptions {
|
|
472
|
+
modal: boolean;
|
|
473
|
+
dismissible: boolean;
|
|
474
|
+
zIndex: number;
|
|
475
|
+
}
|
|
476
|
+
interface DialogInstance {
|
|
477
|
+
id: string;
|
|
478
|
+
templateKey: string;
|
|
479
|
+
payload: unknown;
|
|
480
|
+
options: DialogOptions;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
type OpenDialogCommand = {
|
|
484
|
+
templateKey: string;
|
|
485
|
+
payload?: unknown;
|
|
486
|
+
options?: DialogOptions;
|
|
487
|
+
};
|
|
488
|
+
interface OpenDialog {
|
|
489
|
+
execute<T = unknown>(cmd: OpenDialogCommand): Promise<T | undefined>;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
declare function useDialog(): {
|
|
493
|
+
open: (cmd: Parameters<(<T>(cmd: OpenDialogCommand) => Promise<T | undefined>)>[0]) => Promise<unknown>;
|
|
494
|
+
resolve: (id: string, result?: unknown) => void;
|
|
495
|
+
dismiss: (id: string) => void;
|
|
496
|
+
closeTop: () => void;
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
interface CloseTopDialog {
|
|
500
|
+
execute(): void;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
interface DismissDialog {
|
|
504
|
+
execute(id: string): void;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
interface ResolveDialog {
|
|
508
|
+
execute(id: string, result?: unknown): void;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
type DialogState = {
|
|
512
|
+
stack: DialogInstance[];
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
interface DialogRegistry {
|
|
516
|
+
getState(): DialogState;
|
|
517
|
+
subscribe(cb: (s: DialogState) => void): () => void;
|
|
518
|
+
push(instance: DialogInstance): void;
|
|
519
|
+
remove(id: string): void;
|
|
520
|
+
findById(id: string): DialogInstance | undefined;
|
|
521
|
+
createDeferred(id: string): {
|
|
522
|
+
promise: Promise<unknown>;
|
|
523
|
+
resolve: (v?: unknown) => void;
|
|
524
|
+
reject: (r?: unknown) => void;
|
|
525
|
+
};
|
|
526
|
+
takeDeferred(id: string): {
|
|
527
|
+
resolve: (v?: unknown) => void;
|
|
528
|
+
reject: (r?: unknown) => void;
|
|
529
|
+
} | undefined;
|
|
530
|
+
getTop(): DialogInstance | undefined;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
declare class DialogController {
|
|
534
|
+
private readonly registry;
|
|
535
|
+
private readonly open;
|
|
536
|
+
private readonly resolve;
|
|
537
|
+
private readonly dismiss;
|
|
538
|
+
private readonly closeTop;
|
|
539
|
+
constructor(registry: DialogRegistry, open: OpenDialog, resolve: ResolveDialog, dismiss: DismissDialog, closeTop: CloseTopDialog);
|
|
540
|
+
handleOpen<T>(cmd: OpenDialogCommand): Promise<T | undefined>;
|
|
541
|
+
handleResolve(id: string, result?: unknown): void;
|
|
542
|
+
handleDismiss(id: string): void;
|
|
543
|
+
handleCloseTop(): void;
|
|
544
|
+
handleGetRegistry(): DialogRegistry;
|
|
545
|
+
}
|
|
546
|
+
declare const dialogController: DialogController;
|
|
547
|
+
|
|
548
|
+
declare const dialogPanelVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
549
|
+
declare function DialogContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
|
|
550
|
+
interface DialogProps<TPayload = unknown> extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>, VariantProps<typeof dialogPanelVariants> {
|
|
551
|
+
id: string;
|
|
552
|
+
template: DialogTemplate<TPayload>;
|
|
553
|
+
payload: TPayload;
|
|
554
|
+
trigger?: React.ReactElement;
|
|
555
|
+
modal?: boolean;
|
|
556
|
+
dismissible?: boolean;
|
|
557
|
+
zIndex?: number;
|
|
558
|
+
maxWidthPx?: number;
|
|
559
|
+
onDismiss?: () => void;
|
|
560
|
+
onResolve?: (result?: unknown) => void;
|
|
561
|
+
onOpenChange?: (open: boolean) => void;
|
|
562
|
+
showClose?: boolean;
|
|
563
|
+
closeLabel?: string;
|
|
564
|
+
open?: boolean;
|
|
565
|
+
defaultOpen?: boolean;
|
|
566
|
+
}
|
|
567
|
+
declare function Dialog<TPayload>({ id, template, payload, trigger, modal, dismissible, zIndex, maxWidthPx, onDismiss, onResolve, onOpenChange, showClose, closeLabel, open, defaultOpen, className, style, ...props }: DialogProps<TPayload>): react_jsx_runtime.JSX.Element;
|
|
568
|
+
|
|
412
569
|
type ControlLikeProps = {
|
|
413
570
|
id?: string;
|
|
414
571
|
disabled?: boolean;
|
|
@@ -475,7 +632,8 @@ type Props = {
|
|
|
475
632
|
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
476
633
|
sideOffset?: number;
|
|
477
634
|
maxWidthPx?: number;
|
|
635
|
+
preserveWhitespace?: boolean;
|
|
478
636
|
};
|
|
479
|
-
declare function Tooltip({ children, content, delayMs, side, sideOffset, maxWidthPx, }: Props): react_jsx_runtime.JSX.Element;
|
|
637
|
+
declare function Tooltip({ children, content, delayMs, side, sideOffset, maxWidthPx, preserveWhitespace, }: Props): react_jsx_runtime.JSX.Element;
|
|
480
638
|
|
|
481
|
-
export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthProvider, type AuthState, AuthStateCtx, Button, type ButtonProps, type CacheInstruction, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type ErrorResponse, Field, type FieldProps, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, Input, type InputProps, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, RedirectIfAuthed, type RedirectIfAuthedProps, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, Skeleton, type SkeletonProps, Textarea, type TextareaProps, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, Tooltip, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, httpClient as fetchHttpClient, notifierController, resolveToastTheme, ui, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useResponsiveMutation };
|
|
639
|
+
export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthProvider, type AuthState, AuthStateCtx, Button, type ButtonProps, type CacheInstruction, ConfirmDialog, type ConfirmDialogProps, type ConfirmPayload, CustomDialog, type CustomDialogPayload, type CustomDialogProps, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type DefaultDialogPayloads, type DefaultDialogTemplateKey, DefaultDialogTemplateKeys, Dialog, DialogContent, DialogController, DialogHost, type DialogInstance, type DialogOptions, type DialogProps, type DialogTemplate, type ErrorResponse, Field, type FieldProps, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, InfoDialog, type InfoDialogProps, type InfoPayload, Input, type InputProps, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, RedirectIfAuthed, type RedirectIfAuthedProps, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, Skeleton, type SkeletonProps, Textarea, type TextareaProps, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, Tooltip, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, dialogController, httpClient as fetchHttpClient, getDialogTemplate, notifierController, registerDefaultDialogs, registerDialogTemplate, resolveToastTheme, ui, unregisterDialogTemplate, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useDialog, useResponsiveMutation };
|
package/dist/index.js
CHANGED
|
@@ -1026,7 +1026,7 @@ var MockAuthHttpClient = class extends MockHttpClient {
|
|
|
1026
1026
|
}
|
|
1027
1027
|
registerAuthRoutes() {
|
|
1028
1028
|
this.register("GET", "/auth/me", async () => {
|
|
1029
|
-
await new Promise((
|
|
1029
|
+
await new Promise((resolve2) => setTimeout(resolve2, this.delayMs));
|
|
1030
1030
|
if (this.fixtures.meError) {
|
|
1031
1031
|
throw this.fixtures.meError;
|
|
1032
1032
|
}
|
|
@@ -1036,7 +1036,7 @@ var MockAuthHttpClient = class extends MockHttpClient {
|
|
|
1036
1036
|
throw unauthorized();
|
|
1037
1037
|
});
|
|
1038
1038
|
this.register("POST", "/auth/login", async (payload) => {
|
|
1039
|
-
await new Promise((
|
|
1039
|
+
await new Promise((resolve2) => setTimeout(resolve2, this.delayMs));
|
|
1040
1040
|
if (this.fixtures.loginError) {
|
|
1041
1041
|
throw this.fixtures.loginError;
|
|
1042
1042
|
}
|
|
@@ -1048,14 +1048,14 @@ var MockAuthHttpClient = class extends MockHttpClient {
|
|
|
1048
1048
|
return httpResponse({ message: "Logged in" });
|
|
1049
1049
|
});
|
|
1050
1050
|
this.register("POST", "/auth/register", async () => {
|
|
1051
|
-
await new Promise((
|
|
1051
|
+
await new Promise((resolve2) => setTimeout(resolve2, this.delayMs));
|
|
1052
1052
|
if (this.fixtures.registerError) {
|
|
1053
1053
|
throw this.fixtures.registerError;
|
|
1054
1054
|
}
|
|
1055
1055
|
return httpResponse({ message: "Registered" });
|
|
1056
1056
|
});
|
|
1057
1057
|
this.register("POST", "/auth/logout", async () => {
|
|
1058
|
-
await new Promise((
|
|
1058
|
+
await new Promise((resolve2) => setTimeout(resolve2, this.delayMs));
|
|
1059
1059
|
if (this.fixtures.logoutError) {
|
|
1060
1060
|
throw this.fixtures.logoutError;
|
|
1061
1061
|
}
|
|
@@ -1065,6 +1065,9 @@ var MockAuthHttpClient = class extends MockHttpClient {
|
|
|
1065
1065
|
}
|
|
1066
1066
|
};
|
|
1067
1067
|
|
|
1068
|
+
// src/ui/components/dialog/dialog-variant/ConfirmDialog.tsx
|
|
1069
|
+
import { Dialog as DialogPrimitive2 } from "radix-ui";
|
|
1070
|
+
|
|
1068
1071
|
// src/ui/components/Button.tsx
|
|
1069
1072
|
import { cva } from "class-variance-authority";
|
|
1070
1073
|
import { Slot } from "radix-ui";
|
|
@@ -1537,14 +1540,419 @@ var Button = React.forwardRef(
|
|
|
1537
1540
|
);
|
|
1538
1541
|
Button.displayName = "Button";
|
|
1539
1542
|
|
|
1540
|
-
// src/ui/components/
|
|
1543
|
+
// src/ui/components/dialog/Dialog.tsx
|
|
1544
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
1545
|
+
import { XIcon } from "lucide-react";
|
|
1546
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
1547
|
+
import * as React2 from "react";
|
|
1548
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1549
|
+
var dialogPanelVariants = cva2(
|
|
1550
|
+
cn(
|
|
1551
|
+
"fixed left-1/2 top-1/2",
|
|
1552
|
+
"-translate-x-1/2 -translate-y-1/2",
|
|
1553
|
+
"w-[min(92vw,var(--dialog-width))]",
|
|
1554
|
+
"pointer-events-auto",
|
|
1555
|
+
"data-[state=open]:animate-[dialog-fade-in_var(--motion-med)_cubic-bezier(0.16,1,0.3,1)]",
|
|
1556
|
+
"data-[state=closed]:animate-[dialog-fade-out_var(--motion-fast)_cubic-bezier(0.4,0,1,1)]",
|
|
1557
|
+
"motion-reduce:animate-none",
|
|
1558
|
+
"data-[state=closed]:pointer-events-none"
|
|
1559
|
+
)
|
|
1560
|
+
);
|
|
1561
|
+
var dialogOverlayClass = cn(
|
|
1562
|
+
"fixed inset-0 bg-[color:var(--overlay)]",
|
|
1563
|
+
"data-[state=open]:animate-[dialog-overlay-in_var(--motion-med)_cubic-bezier(0.16,1,0.3,1)]",
|
|
1564
|
+
"data-[state=closed]:animate-[dialog-overlay-out_var(--motion-fast)_cubic-bezier(0.4,0,1,1)]",
|
|
1565
|
+
"motion-reduce:animate-none",
|
|
1566
|
+
"data-[state=closed]:pointer-events-none"
|
|
1567
|
+
);
|
|
1568
|
+
function DialogContent({ className, ...props }) {
|
|
1569
|
+
return /* @__PURE__ */ jsx7("div", { className: cn("DialogContent p-6", className), ...props });
|
|
1570
|
+
}
|
|
1571
|
+
function AutoHeight({ children }) {
|
|
1572
|
+
const ref = React2.useRef(null);
|
|
1573
|
+
const [height, setHeight] = React2.useState("auto");
|
|
1574
|
+
React2.useLayoutEffect(() => {
|
|
1575
|
+
const el = ref.current;
|
|
1576
|
+
if (!el) return;
|
|
1577
|
+
const dpr = Math.max(1, Math.round(window.devicePixelRatio || 1));
|
|
1578
|
+
let raf = 0;
|
|
1579
|
+
const ro = new ResizeObserver((entries) => {
|
|
1580
|
+
const entry = entries[0];
|
|
1581
|
+
const raw = entry.borderBoxSize?.[0]?.blockSize ?? entry.contentRect.height;
|
|
1582
|
+
const snapped = Math.round(raw * dpr) / dpr;
|
|
1583
|
+
raf = requestAnimationFrame(() => {
|
|
1584
|
+
setHeight((prev) => {
|
|
1585
|
+
const prevNum = prev === "auto" ? -1 : prev;
|
|
1586
|
+
if (prevNum < 0 || Math.abs(snapped - prevNum) >= 2) return snapped;
|
|
1587
|
+
return prev;
|
|
1588
|
+
});
|
|
1589
|
+
});
|
|
1590
|
+
});
|
|
1591
|
+
ro.observe(el);
|
|
1592
|
+
return () => {
|
|
1593
|
+
ro.disconnect();
|
|
1594
|
+
cancelAnimationFrame(raf);
|
|
1595
|
+
};
|
|
1596
|
+
}, []);
|
|
1597
|
+
return /* @__PURE__ */ jsx7(
|
|
1598
|
+
"div",
|
|
1599
|
+
{
|
|
1600
|
+
className: "transition-[height] duration-(--motion-med) ease",
|
|
1601
|
+
style: { height: height === "auto" ? "auto" : height, overflow: "hidden", willChange: "height" },
|
|
1602
|
+
children: /* @__PURE__ */ jsx7("div", { ref, style: { boxSizing: "border-box" }, children })
|
|
1603
|
+
}
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
function Dialog({
|
|
1607
|
+
id,
|
|
1608
|
+
template,
|
|
1609
|
+
payload,
|
|
1610
|
+
trigger,
|
|
1611
|
+
modal = true,
|
|
1612
|
+
dismissible = true,
|
|
1613
|
+
zIndex = 0,
|
|
1614
|
+
maxWidthPx = 800,
|
|
1615
|
+
onDismiss,
|
|
1616
|
+
onResolve,
|
|
1617
|
+
onOpenChange,
|
|
1618
|
+
showClose = true,
|
|
1619
|
+
closeLabel = "Close dialog",
|
|
1620
|
+
open: open2,
|
|
1621
|
+
defaultOpen,
|
|
1622
|
+
className,
|
|
1623
|
+
style,
|
|
1624
|
+
...props
|
|
1625
|
+
}) {
|
|
1626
|
+
const fallbackId = React2.useId();
|
|
1627
|
+
const resolvedRef = React2.useRef(false);
|
|
1628
|
+
const Template = template;
|
|
1629
|
+
const handleOpenChange = (nextOpen) => {
|
|
1630
|
+
onOpenChange?.(nextOpen);
|
|
1631
|
+
if (nextOpen) {
|
|
1632
|
+
resolvedRef.current = false;
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
if (resolvedRef.current) {
|
|
1636
|
+
resolvedRef.current = false;
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
onDismiss?.();
|
|
1640
|
+
};
|
|
1641
|
+
const handleResolve = React2.useCallback(
|
|
1642
|
+
(result) => {
|
|
1643
|
+
resolvedRef.current = true;
|
|
1644
|
+
onResolve?.(result);
|
|
1645
|
+
},
|
|
1646
|
+
[onResolve]
|
|
1647
|
+
);
|
|
1648
|
+
return /* @__PURE__ */ jsxs3(DialogPrimitive.Root, { open: open2, defaultOpen, onOpenChange: handleOpenChange, modal, children: [
|
|
1649
|
+
trigger ? /* @__PURE__ */ jsx7(DialogPrimitive.Trigger, { asChild: true, children: trigger }) : null,
|
|
1650
|
+
/* @__PURE__ */ jsxs3(DialogPrimitive.Portal, { children: [
|
|
1651
|
+
modal ? /* @__PURE__ */ jsx7(
|
|
1652
|
+
DialogPrimitive.Overlay,
|
|
1653
|
+
{
|
|
1654
|
+
className: cn("DialogOverlay", dialogOverlayClass),
|
|
1655
|
+
style: { zIndex: zIndex - 1 }
|
|
1656
|
+
}
|
|
1657
|
+
) : null,
|
|
1658
|
+
/* @__PURE__ */ jsx7(
|
|
1659
|
+
DialogPrimitive.Content,
|
|
1660
|
+
{
|
|
1661
|
+
className: cn(
|
|
1662
|
+
"DialogContent",
|
|
1663
|
+
dialogPanelVariants(),
|
|
1664
|
+
"data-[state=open]:[&_.dialog-surface]:animate-[dialog-surface-in_var(--motion-med)_cubic-bezier(0.16,1,0.3,1)]",
|
|
1665
|
+
"data-[state=closed]:[&_.dialog-surface]:animate-[dialog-surface-out_var(--motion-fast)_cubic-bezier(0.4,0,1,1)]",
|
|
1666
|
+
"motion-reduce:[&_.dialog-surface]:animate-none",
|
|
1667
|
+
className
|
|
1668
|
+
),
|
|
1669
|
+
style: {
|
|
1670
|
+
...style,
|
|
1671
|
+
zIndex,
|
|
1672
|
+
"--dialog-width": `${maxWidthPx}px`
|
|
1673
|
+
},
|
|
1674
|
+
onInteractOutside: (event) => {
|
|
1675
|
+
if (!dismissible) event.preventDefault();
|
|
1676
|
+
},
|
|
1677
|
+
onEscapeKeyDown: (event) => {
|
|
1678
|
+
if (!dismissible) event.preventDefault();
|
|
1679
|
+
},
|
|
1680
|
+
...props,
|
|
1681
|
+
children: /* @__PURE__ */ jsxs3("div", { className: "dialog-surface relative shell overflow-hidden", children: [
|
|
1682
|
+
showClose ? /* @__PURE__ */ jsx7(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx7(
|
|
1683
|
+
Button,
|
|
1684
|
+
{
|
|
1685
|
+
variant: "ghost",
|
|
1686
|
+
size: "icon",
|
|
1687
|
+
leftIcon: /* @__PURE__ */ jsx7(XIcon, { className: "w-5 h-5" }),
|
|
1688
|
+
className: "absolute right-2 top-2 z-10 rounded-full",
|
|
1689
|
+
"aria-label": closeLabel
|
|
1690
|
+
}
|
|
1691
|
+
) }) : null,
|
|
1692
|
+
/* @__PURE__ */ jsx7(AutoHeight, { children: /* @__PURE__ */ jsx7(Template, { id: id ?? fallbackId, payload, onResolve: handleResolve }) })
|
|
1693
|
+
] })
|
|
1694
|
+
}
|
|
1695
|
+
)
|
|
1696
|
+
] })
|
|
1697
|
+
] });
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
// src/ui/components/dialog/dialog-variant/ConfirmDialog.tsx
|
|
1701
|
+
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1702
|
+
var ConfirmDialog = (props) => {
|
|
1703
|
+
const p = props.payload ?? { title: "Are you sure?" };
|
|
1704
|
+
const confirmVariant = p.variant ?? (p.danger ? "danger" : "secondary");
|
|
1705
|
+
return /* @__PURE__ */ jsxs4(DialogContent, { children: [
|
|
1706
|
+
/* @__PURE__ */ jsx8("h3", { className: "text-lg font-semibold", children: p.title }),
|
|
1707
|
+
p.children && p.children,
|
|
1708
|
+
p.message ? /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm opacity-80", children: p.message }) : null,
|
|
1709
|
+
/* @__PURE__ */ jsxs4("div", { className: "mt-5 flex items-center justify-end gap-4", children: [
|
|
1710
|
+
/* @__PURE__ */ jsx8(DialogPrimitive2.Close, { asChild: true, children: /* @__PURE__ */ jsx8(Button, { variant: "secondary", children: p.cancelText ?? "Cancel" }) }),
|
|
1711
|
+
/* @__PURE__ */ jsx8(DialogPrimitive2.Close, { asChild: true, children: /* @__PURE__ */ jsx8(Button, { variant: confirmVariant, onClick: () => props.onResolve?.({ confirmed: true }), children: p.confirmText ?? "Confirm" }) })
|
|
1712
|
+
] })
|
|
1713
|
+
] });
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1716
|
+
// src/ui/components/dialog/dialog-variant/CustomDialog.tsx
|
|
1717
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1718
|
+
var CustomDialog = (props) => {
|
|
1719
|
+
const p = props.payload ?? { children: /* @__PURE__ */ jsx9("div", { children: "Empty custom dialog" }) };
|
|
1720
|
+
return /* @__PURE__ */ jsx9(DialogContent, { children: p.children });
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1723
|
+
// src/ui/components/dialog/dialog-variant/InfoDialog.tsx
|
|
1724
|
+
import { Dialog as DialogPrimitive3 } from "radix-ui";
|
|
1725
|
+
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1726
|
+
var InfoDialog = (props) => {
|
|
1727
|
+
const p = props.payload ?? { title: "Information" };
|
|
1728
|
+
return /* @__PURE__ */ jsxs5(DialogContent, { children: [
|
|
1729
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-lg font-semibold", children: p.title }),
|
|
1730
|
+
p.children,
|
|
1731
|
+
/* @__PURE__ */ jsx10("div", { className: "mt-5 flex items-center justify-end gap-4", children: /* @__PURE__ */ jsx10(DialogPrimitive3.Close, { asChild: true, children: /* @__PURE__ */ jsx10(Button, { variant: "secondary", children: p.confirmText || "Dismiss" }) }) })
|
|
1732
|
+
] });
|
|
1733
|
+
};
|
|
1734
|
+
|
|
1735
|
+
// src/feature/dialog/infra/web/react/DialogTemplate.tsx
|
|
1736
|
+
var templates = /* @__PURE__ */ new Map();
|
|
1737
|
+
function registerDialogTemplate(key, component) {
|
|
1738
|
+
templates.set(key, component);
|
|
1739
|
+
}
|
|
1740
|
+
function unregisterDialogTemplate(key) {
|
|
1741
|
+
templates.delete(key);
|
|
1742
|
+
}
|
|
1743
|
+
function getDialogTemplate(key) {
|
|
1744
|
+
return templates.get(key);
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
// src/feature/dialog/infra/web/react/bootstrap-dialogs.ts
|
|
1748
|
+
function registerDefaultDialogs() {
|
|
1749
|
+
registerDialogTemplate("custom", CustomDialog);
|
|
1750
|
+
registerDialogTemplate("confirm", ConfirmDialog);
|
|
1751
|
+
registerDialogTemplate("info", InfoDialog);
|
|
1752
|
+
}
|
|
1753
|
+
var DefaultDialogTemplateKeys = ["custom", "confirm", "info"];
|
|
1754
|
+
|
|
1755
|
+
// src/feature/dialog/infra/web/react/DialogHost.tsx
|
|
1541
1756
|
import * as React3 from "react";
|
|
1542
1757
|
|
|
1758
|
+
// src/feature/dialog/application/use-case/close-top-dialog-use-case.ts
|
|
1759
|
+
var CloseTopUseCase = class {
|
|
1760
|
+
constructor(reg) {
|
|
1761
|
+
this.reg = reg;
|
|
1762
|
+
}
|
|
1763
|
+
execute() {
|
|
1764
|
+
const top = this.reg.getTop();
|
|
1765
|
+
if (!top) return;
|
|
1766
|
+
this.reg.takeDeferred(top.id)?.resolve(void 0);
|
|
1767
|
+
this.reg.remove(top.id);
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1770
|
+
|
|
1771
|
+
// src/feature/dialog/application/use-case/dismiss-dialog-use-case.ts
|
|
1772
|
+
var DismissDialogUseCase = class {
|
|
1773
|
+
constructor(reg) {
|
|
1774
|
+
this.reg = reg;
|
|
1775
|
+
}
|
|
1776
|
+
execute(id) {
|
|
1777
|
+
this.reg.takeDeferred(id)?.resolve(void 0);
|
|
1778
|
+
this.reg.remove(id);
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
|
|
1782
|
+
// src/feature/dialog/application/use-case/open-dialog-use-case.ts
|
|
1783
|
+
import { v4 as uuid } from "uuid";
|
|
1784
|
+
var OpenDialogUseCase = class {
|
|
1785
|
+
constructor(reg) {
|
|
1786
|
+
this.reg = reg;
|
|
1787
|
+
}
|
|
1788
|
+
async execute(cmd) {
|
|
1789
|
+
const id = uuid();
|
|
1790
|
+
const options = cmd.options ?? getDefaultOptions();
|
|
1791
|
+
if (!options.zIndex) {
|
|
1792
|
+
options.zIndex = 2e3;
|
|
1793
|
+
}
|
|
1794
|
+
this.reg.push({
|
|
1795
|
+
id,
|
|
1796
|
+
templateKey: cmd.templateKey,
|
|
1797
|
+
payload: cmd.payload ?? {},
|
|
1798
|
+
options
|
|
1799
|
+
});
|
|
1800
|
+
const { promise } = this.reg.createDeferred(id);
|
|
1801
|
+
const result = await promise;
|
|
1802
|
+
return result;
|
|
1803
|
+
}
|
|
1804
|
+
};
|
|
1805
|
+
function getDefaultOptions() {
|
|
1806
|
+
return {
|
|
1807
|
+
modal: true,
|
|
1808
|
+
dismissible: true,
|
|
1809
|
+
zIndex: 2500
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
// src/feature/dialog/application/use-case/resolve-dialog-use-case.ts
|
|
1814
|
+
var ResolveDialogUseCase = class {
|
|
1815
|
+
constructor(reg) {
|
|
1816
|
+
this.reg = reg;
|
|
1817
|
+
}
|
|
1818
|
+
execute(id, result) {
|
|
1819
|
+
this.reg.takeDeferred(id)?.resolve(result);
|
|
1820
|
+
this.reg.remove(id);
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
// src/feature/dialog/infra/provider/in-memory-dialog-registry.ts
|
|
1825
|
+
var InMemoryDialogRegistry = class {
|
|
1826
|
+
state = { stack: [] };
|
|
1827
|
+
subs = /* @__PURE__ */ new Set();
|
|
1828
|
+
deferred = /* @__PURE__ */ new Map();
|
|
1829
|
+
getState() {
|
|
1830
|
+
return this.state;
|
|
1831
|
+
}
|
|
1832
|
+
subscribe(cb) {
|
|
1833
|
+
this.subs.add(cb);
|
|
1834
|
+
cb(this.state);
|
|
1835
|
+
return () => this.subs.delete(cb);
|
|
1836
|
+
}
|
|
1837
|
+
emit() {
|
|
1838
|
+
for (const cb of this.subs) cb(this.state);
|
|
1839
|
+
}
|
|
1840
|
+
push(instance) {
|
|
1841
|
+
this.state = { stack: [...this.state.stack, instance] };
|
|
1842
|
+
this.emit();
|
|
1843
|
+
}
|
|
1844
|
+
remove(id) {
|
|
1845
|
+
this.state = { stack: this.state.stack.filter((d) => d.id !== id) };
|
|
1846
|
+
this.emit();
|
|
1847
|
+
}
|
|
1848
|
+
findById(id) {
|
|
1849
|
+
return this.state.stack.find((d) => d.id === id);
|
|
1850
|
+
}
|
|
1851
|
+
getTop() {
|
|
1852
|
+
const s = this.state.stack;
|
|
1853
|
+
return s.length ? s[s.length - 1] : void 0;
|
|
1854
|
+
}
|
|
1855
|
+
createDeferred(id) {
|
|
1856
|
+
let resolve2;
|
|
1857
|
+
let reject;
|
|
1858
|
+
const promise = new Promise((res, rej) => {
|
|
1859
|
+
resolve2 = res;
|
|
1860
|
+
reject = rej;
|
|
1861
|
+
});
|
|
1862
|
+
this.deferred.set(id, { resolve: resolve2, reject });
|
|
1863
|
+
return { promise, resolve: resolve2, reject };
|
|
1864
|
+
}
|
|
1865
|
+
takeDeferred(id) {
|
|
1866
|
+
const d = this.deferred.get(id);
|
|
1867
|
+
this.deferred.delete(id);
|
|
1868
|
+
return d;
|
|
1869
|
+
}
|
|
1870
|
+
};
|
|
1871
|
+
|
|
1872
|
+
// src/feature/dialog/infra/controller/dialog-controller.ts
|
|
1873
|
+
var DialogController = class {
|
|
1874
|
+
constructor(registry2, open2, resolve2, dismiss2, closeTop2) {
|
|
1875
|
+
this.registry = registry2;
|
|
1876
|
+
this.open = open2;
|
|
1877
|
+
this.resolve = resolve2;
|
|
1878
|
+
this.dismiss = dismiss2;
|
|
1879
|
+
this.closeTop = closeTop2;
|
|
1880
|
+
}
|
|
1881
|
+
handleOpen(cmd) {
|
|
1882
|
+
return this.open.execute(cmd);
|
|
1883
|
+
}
|
|
1884
|
+
handleResolve(id, result) {
|
|
1885
|
+
return this.resolve.execute(id, result);
|
|
1886
|
+
}
|
|
1887
|
+
handleDismiss(id) {
|
|
1888
|
+
return this.dismiss.execute(id);
|
|
1889
|
+
}
|
|
1890
|
+
handleCloseTop() {
|
|
1891
|
+
return this.closeTop.execute();
|
|
1892
|
+
}
|
|
1893
|
+
handleGetRegistry() {
|
|
1894
|
+
return this.registry;
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
var registry = new InMemoryDialogRegistry();
|
|
1898
|
+
var open = new OpenDialogUseCase(registry);
|
|
1899
|
+
var resolve = new ResolveDialogUseCase(registry);
|
|
1900
|
+
var dismiss = new DismissDialogUseCase(registry);
|
|
1901
|
+
var closeTop = new CloseTopUseCase(registry);
|
|
1902
|
+
var dialogController = new DialogController(registry, open, resolve, dismiss, closeTop);
|
|
1903
|
+
|
|
1904
|
+
// src/feature/dialog/infra/web/react/DialogHost.tsx
|
|
1905
|
+
import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
|
|
1906
|
+
var DialogHost = () => {
|
|
1907
|
+
const [state, setState] = React3.useState(dialogController.handleGetRegistry().getState());
|
|
1908
|
+
React3.useEffect(() => dialogController.handleGetRegistry().subscribe(setState), []);
|
|
1909
|
+
return /* @__PURE__ */ jsx11(Fragment2, { children: state.stack.map((dialog, index) => {
|
|
1910
|
+
const template = getDialogTemplate(dialog.templateKey);
|
|
1911
|
+
if (!template) {
|
|
1912
|
+
console.error(`Missing dialog template: ${dialog.templateKey}`);
|
|
1913
|
+
return null;
|
|
1914
|
+
}
|
|
1915
|
+
return /* @__PURE__ */ jsx11(
|
|
1916
|
+
Dialog,
|
|
1917
|
+
{
|
|
1918
|
+
id: dialog.id,
|
|
1919
|
+
template,
|
|
1920
|
+
payload: dialog.payload,
|
|
1921
|
+
modal: dialog.options.modal,
|
|
1922
|
+
dismissible: dialog.options.dismissible,
|
|
1923
|
+
zIndex: dialog.options.zIndex + index,
|
|
1924
|
+
defaultOpen: true,
|
|
1925
|
+
onResolve: (result) => dialogController.handleResolve(dialog.id, result),
|
|
1926
|
+
onDismiss: () => dialogController.handleDismiss(dialog.id)
|
|
1927
|
+
},
|
|
1928
|
+
dialog.id
|
|
1929
|
+
);
|
|
1930
|
+
}) });
|
|
1931
|
+
};
|
|
1932
|
+
|
|
1933
|
+
// src/feature/dialog/infra/web/react/useDialog.tsx
|
|
1934
|
+
import { useMemo as useMemo3 } from "react";
|
|
1935
|
+
function useDialog() {
|
|
1936
|
+
const c = dialogController;
|
|
1937
|
+
return useMemo3(
|
|
1938
|
+
() => ({
|
|
1939
|
+
open: (cmd) => c.handleOpen(cmd),
|
|
1940
|
+
resolve: (id, result) => c.handleResolve(id, result),
|
|
1941
|
+
dismiss: (id) => c.handleDismiss(id),
|
|
1942
|
+
closeTop: () => c.handleCloseTop()
|
|
1943
|
+
}),
|
|
1944
|
+
[c]
|
|
1945
|
+
);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// src/ui/components/Field.tsx
|
|
1949
|
+
import * as React5 from "react";
|
|
1950
|
+
|
|
1543
1951
|
// src/ui/components/Label.tsx
|
|
1544
|
-
import * as
|
|
1545
|
-
import { jsx as
|
|
1546
|
-
var Label =
|
|
1547
|
-
({ className, htmlFor, children, ...props }, ref) => /* @__PURE__ */
|
|
1952
|
+
import * as React4 from "react";
|
|
1953
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1954
|
+
var Label = React4.forwardRef(
|
|
1955
|
+
({ className, htmlFor, children, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
1548
1956
|
"label",
|
|
1549
1957
|
{
|
|
1550
1958
|
ref,
|
|
@@ -1558,9 +1966,9 @@ var Label = React2.forwardRef(
|
|
|
1558
1966
|
Label.displayName = "Label";
|
|
1559
1967
|
|
|
1560
1968
|
// src/ui/components/Field.tsx
|
|
1561
|
-
import { jsx as
|
|
1969
|
+
import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1562
1970
|
function Field({ label, hint, error, required, disabled, id, children, className, ...props }) {
|
|
1563
|
-
const reactId =
|
|
1971
|
+
const reactId = React5.useId();
|
|
1564
1972
|
const controlId = id ?? `field-${reactId}`;
|
|
1565
1973
|
const hintId = hint ? `${controlId}-hint` : void 0;
|
|
1566
1974
|
const errorId = error ? `${controlId}-error` : void 0;
|
|
@@ -1570,31 +1978,31 @@ function Field({ label, hint, error, required, disabled, id, children, className
|
|
|
1570
1978
|
const ariaDescribedBy = describedByParts.length ? describedByParts.join(" ") : void 0;
|
|
1571
1979
|
const resolvedDisabled = disabled ?? children.props.disabled;
|
|
1572
1980
|
const resolvedRequired = required ?? children.props.required;
|
|
1573
|
-
const control =
|
|
1981
|
+
const control = React5.cloneElement(children, {
|
|
1574
1982
|
id: controlId,
|
|
1575
1983
|
disabled: resolvedDisabled,
|
|
1576
1984
|
required: resolvedRequired,
|
|
1577
1985
|
invalid,
|
|
1578
1986
|
"aria-describedby": ariaDescribedBy
|
|
1579
1987
|
});
|
|
1580
|
-
return /* @__PURE__ */
|
|
1581
|
-
label ? /* @__PURE__ */
|
|
1988
|
+
return /* @__PURE__ */ jsxs6("div", { className: cn("grid gap-1.5", className), ...props, children: [
|
|
1989
|
+
label ? /* @__PURE__ */ jsx13("div", { className: "flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs6(Label, { htmlFor: controlId, children: [
|
|
1582
1990
|
label,
|
|
1583
|
-
resolvedRequired ? /* @__PURE__ */
|
|
1991
|
+
resolvedRequired ? /* @__PURE__ */ jsxs6("span", { "aria-hidden": "true", className: "text-(--muted)", children: [
|
|
1584
1992
|
" ",
|
|
1585
1993
|
"*"
|
|
1586
1994
|
] }) : null
|
|
1587
1995
|
] }) }) : null,
|
|
1588
1996
|
control,
|
|
1589
|
-
error ? /* @__PURE__ */
|
|
1590
|
-
hint ? /* @__PURE__ */
|
|
1997
|
+
error ? /* @__PURE__ */ jsx13("p", { id: errorId, className: "text-xs leading-5 text-(--danger-contrast)", role: "alert", children: error }) : null,
|
|
1998
|
+
hint ? /* @__PURE__ */ jsx13("p", { id: hintId, className: "text-xs leading-5 text-(--muted)", children: hint }) : null
|
|
1591
1999
|
] });
|
|
1592
2000
|
}
|
|
1593
2001
|
|
|
1594
2002
|
// src/ui/components/Input.tsx
|
|
1595
|
-
import { cva as
|
|
1596
|
-
import * as
|
|
1597
|
-
import { jsx as
|
|
2003
|
+
import { cva as cva3 } from "class-variance-authority";
|
|
2004
|
+
import * as React6 from "react";
|
|
2005
|
+
import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1598
2006
|
var controlShellBase = cn(
|
|
1599
2007
|
"relative inline-flex items-center gap-2",
|
|
1600
2008
|
"rounded-[var(--radius-input)]",
|
|
@@ -1611,7 +2019,7 @@ var controlShellBase = cn(
|
|
|
1611
2019
|
"data-[disabled]:border-[color:var(--disabled-border)]",
|
|
1612
2020
|
"data-[disabled]:cursor-not-allowed"
|
|
1613
2021
|
);
|
|
1614
|
-
var controlShellVariants =
|
|
2022
|
+
var controlShellVariants = cva3(controlShellBase, {
|
|
1615
2023
|
variants: {
|
|
1616
2024
|
variant: {
|
|
1617
2025
|
surface: cn("bg-[color:var(--surface-2)]", "hover:bg-[color:var(--surface-hover)]"),
|
|
@@ -1649,7 +2057,7 @@ var slotBase = cn(
|
|
|
1649
2057
|
"data-[disabled]:text-[color:var(--disabled-fg)]"
|
|
1650
2058
|
);
|
|
1651
2059
|
var slotReserve = "min-w-[var(--input-slot-size)]";
|
|
1652
|
-
var Input =
|
|
2060
|
+
var Input = React6.forwardRef(
|
|
1653
2061
|
({
|
|
1654
2062
|
variant,
|
|
1655
2063
|
size,
|
|
@@ -1667,14 +2075,14 @@ var Input = React4.forwardRef(
|
|
|
1667
2075
|
const isDisabled = Boolean(disabled);
|
|
1668
2076
|
const showLeftSlot = Boolean(leftSlot || reserveLeftSlot);
|
|
1669
2077
|
const showRightSlot = Boolean(rightSlot || reserveRightSlot);
|
|
1670
|
-
return /* @__PURE__ */
|
|
2078
|
+
return /* @__PURE__ */ jsxs7(
|
|
1671
2079
|
"div",
|
|
1672
2080
|
{
|
|
1673
2081
|
className: cn(controlShellVariants({ variant, size, fullWidth }), className),
|
|
1674
2082
|
"data-invalid": invalid ? "" : void 0,
|
|
1675
2083
|
"data-disabled": isDisabled ? "" : void 0,
|
|
1676
2084
|
children: [
|
|
1677
|
-
showLeftSlot ? /* @__PURE__ */
|
|
2085
|
+
showLeftSlot ? /* @__PURE__ */ jsx14(
|
|
1678
2086
|
"span",
|
|
1679
2087
|
{
|
|
1680
2088
|
className: cn(slotBase, reserveLeftSlot && slotReserve),
|
|
@@ -1682,7 +2090,7 @@ var Input = React4.forwardRef(
|
|
|
1682
2090
|
children: leftSlot
|
|
1683
2091
|
}
|
|
1684
2092
|
) : null,
|
|
1685
|
-
/* @__PURE__ */
|
|
2093
|
+
/* @__PURE__ */ jsx14(
|
|
1686
2094
|
"input",
|
|
1687
2095
|
{
|
|
1688
2096
|
ref,
|
|
@@ -1692,7 +2100,7 @@ var Input = React4.forwardRef(
|
|
|
1692
2100
|
...props
|
|
1693
2101
|
}
|
|
1694
2102
|
),
|
|
1695
|
-
showRightSlot ? /* @__PURE__ */
|
|
2103
|
+
showRightSlot ? /* @__PURE__ */ jsx14(
|
|
1696
2104
|
"span",
|
|
1697
2105
|
{
|
|
1698
2106
|
className: cn(slotBase, reserveRightSlot && slotReserve),
|
|
@@ -1708,9 +2116,9 @@ var Input = React4.forwardRef(
|
|
|
1708
2116
|
Input.displayName = "Input";
|
|
1709
2117
|
|
|
1710
2118
|
// src/ui/components/Skeleton.tsx
|
|
1711
|
-
import { cva as
|
|
1712
|
-
import * as
|
|
1713
|
-
import { jsx as
|
|
2119
|
+
import { cva as cva4 } from "class-variance-authority";
|
|
2120
|
+
import * as React7 from "react";
|
|
2121
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1714
2122
|
var skeletonBase = cn(
|
|
1715
2123
|
"relative isolate inline-flex overflow-hidden",
|
|
1716
2124
|
"bg-[color:color-mix(in_oklab,var(--surface-2),var(--border)_25%)]",
|
|
@@ -1723,7 +2131,7 @@ var shimmerEffect = cn(
|
|
|
1723
2131
|
"before:[background-size:200%_100%]",
|
|
1724
2132
|
"before:animate-[skeleton-shimmer_1.6s_linear_infinite] motion-reduce:before:animate-none"
|
|
1725
2133
|
);
|
|
1726
|
-
var skeletonVariants =
|
|
2134
|
+
var skeletonVariants = cva4(skeletonBase, {
|
|
1727
2135
|
variants: {
|
|
1728
2136
|
variant: {
|
|
1729
2137
|
surface: "",
|
|
@@ -1764,10 +2172,10 @@ var skeletonVariants = cva3(skeletonBase, {
|
|
|
1764
2172
|
preset: "none"
|
|
1765
2173
|
}
|
|
1766
2174
|
});
|
|
1767
|
-
var Skeleton =
|
|
2175
|
+
var Skeleton = React7.forwardRef(
|
|
1768
2176
|
({ variant, size, radius, fullWidth, animation, preset, animate, className, ...props }, ref) => {
|
|
1769
2177
|
const resolvedAnimation = animation ?? (animate === false ? "none" : animate ? "pulse" : void 0);
|
|
1770
|
-
return /* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsx15(
|
|
1771
2179
|
"div",
|
|
1772
2180
|
{
|
|
1773
2181
|
ref,
|
|
@@ -1790,9 +2198,9 @@ var Skeleton = React5.forwardRef(
|
|
|
1790
2198
|
Skeleton.displayName = "Skeleton";
|
|
1791
2199
|
|
|
1792
2200
|
// src/ui/components/Textarea.tsx
|
|
1793
|
-
import { cva as
|
|
1794
|
-
import * as
|
|
1795
|
-
import { jsx as
|
|
2201
|
+
import { cva as cva5 } from "class-variance-authority";
|
|
2202
|
+
import * as React8 from "react";
|
|
2203
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1796
2204
|
var controlShellBase2 = cn(
|
|
1797
2205
|
"relative inline-flex w-full",
|
|
1798
2206
|
"rounded-[var(--radius-input)]",
|
|
@@ -1809,7 +2217,7 @@ var controlShellBase2 = cn(
|
|
|
1809
2217
|
"data-[disabled]:border-[color:var(--disabled-border)]",
|
|
1810
2218
|
"data-[disabled]:cursor-not-allowed"
|
|
1811
2219
|
);
|
|
1812
|
-
var textareaShellVariants =
|
|
2220
|
+
var textareaShellVariants = cva5(controlShellBase2, {
|
|
1813
2221
|
variants: {
|
|
1814
2222
|
variant: {
|
|
1815
2223
|
surface: cn("bg-[color:var(--surface-2)]", "hover:bg-[color:var(--surface-hover)]"),
|
|
@@ -1854,7 +2262,7 @@ function mergeRefs(...refs) {
|
|
|
1854
2262
|
}
|
|
1855
2263
|
};
|
|
1856
2264
|
}
|
|
1857
|
-
var Textarea =
|
|
2265
|
+
var Textarea = React8.forwardRef(
|
|
1858
2266
|
({
|
|
1859
2267
|
variant,
|
|
1860
2268
|
size,
|
|
@@ -1871,8 +2279,8 @@ var Textarea = React6.forwardRef(
|
|
|
1871
2279
|
...props
|
|
1872
2280
|
}, ref) => {
|
|
1873
2281
|
const isDisabled = Boolean(disabled);
|
|
1874
|
-
const innerRef =
|
|
1875
|
-
const resize =
|
|
2282
|
+
const innerRef = React8.useRef(null);
|
|
2283
|
+
const resize = React8.useCallback(() => {
|
|
1876
2284
|
if (!autoResize) return;
|
|
1877
2285
|
const el = innerRef.current;
|
|
1878
2286
|
if (!el) return;
|
|
@@ -1884,16 +2292,16 @@ var Textarea = React6.forwardRef(
|
|
|
1884
2292
|
resize();
|
|
1885
2293
|
onInput?.(e);
|
|
1886
2294
|
};
|
|
1887
|
-
|
|
2295
|
+
React8.useLayoutEffect(() => {
|
|
1888
2296
|
resize();
|
|
1889
2297
|
}, [resize, value]);
|
|
1890
|
-
return /* @__PURE__ */
|
|
2298
|
+
return /* @__PURE__ */ jsx16(
|
|
1891
2299
|
"div",
|
|
1892
2300
|
{
|
|
1893
2301
|
className: cn(textareaShellVariants({ variant, size, fullWidth }), className),
|
|
1894
2302
|
"data-invalid": invalid ? "" : void 0,
|
|
1895
2303
|
"data-disabled": isDisabled ? "" : void 0,
|
|
1896
|
-
children: /* @__PURE__ */
|
|
2304
|
+
children: /* @__PURE__ */ jsx16(
|
|
1897
2305
|
"textarea",
|
|
1898
2306
|
{
|
|
1899
2307
|
ref: mergeRefs(innerRef, ref),
|
|
@@ -1918,7 +2326,7 @@ Textarea.displayName = "Textarea";
|
|
|
1918
2326
|
|
|
1919
2327
|
// src/ui/components/Tooltip.tsx
|
|
1920
2328
|
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
1921
|
-
import { jsx as
|
|
2329
|
+
import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1922
2330
|
var tooltipContentBase = cn(
|
|
1923
2331
|
"panel shadow-none px-4 py-2.5 text-xs z-5000 select-none",
|
|
1924
2332
|
"origin-center will-change-[transform,opacity]",
|
|
@@ -1937,11 +2345,12 @@ function Tooltip({
|
|
|
1937
2345
|
delayMs = 300,
|
|
1938
2346
|
side = "top",
|
|
1939
2347
|
sideOffset = 12,
|
|
1940
|
-
maxWidthPx = 240
|
|
2348
|
+
maxWidthPx = 240,
|
|
2349
|
+
preserveWhitespace = false
|
|
1941
2350
|
}) {
|
|
1942
|
-
return /* @__PURE__ */
|
|
1943
|
-
/* @__PURE__ */
|
|
1944
|
-
/* @__PURE__ */
|
|
2351
|
+
return /* @__PURE__ */ jsx17(TooltipPrimitive.Provider, { delayDuration: delayMs, children: /* @__PURE__ */ jsxs8(TooltipPrimitive.Root, { children: [
|
|
2352
|
+
/* @__PURE__ */ jsx17(TooltipPrimitive.Trigger, { asChild: true, children }),
|
|
2353
|
+
/* @__PURE__ */ jsx17(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs8(
|
|
1945
2354
|
TooltipPrimitive.Content,
|
|
1946
2355
|
{
|
|
1947
2356
|
side,
|
|
@@ -1950,13 +2359,13 @@ function Tooltip({
|
|
|
1950
2359
|
style: {
|
|
1951
2360
|
width: "max-content",
|
|
1952
2361
|
maxWidth: `min(${maxWidthPx}px, 90vw)`,
|
|
1953
|
-
whiteSpace: "normal",
|
|
2362
|
+
whiteSpace: preserveWhitespace ? "pre-line" : "normal",
|
|
1954
2363
|
overflowWrap: "break-word",
|
|
1955
2364
|
hyphens: "auto"
|
|
1956
2365
|
},
|
|
1957
2366
|
children: [
|
|
1958
2367
|
content,
|
|
1959
|
-
/* @__PURE__ */
|
|
2368
|
+
/* @__PURE__ */ jsx17(TooltipPrimitive.Arrow, { style: { fill: "var(--surface-2)" } })
|
|
1960
2369
|
]
|
|
1961
2370
|
}
|
|
1962
2371
|
) })
|
|
@@ -1970,9 +2379,17 @@ export {
|
|
|
1970
2379
|
AuthProvider,
|
|
1971
2380
|
AuthStateCtx,
|
|
1972
2381
|
Button,
|
|
2382
|
+
ConfirmDialog,
|
|
2383
|
+
CustomDialog,
|
|
1973
2384
|
DEFAULT_NOTIFICATION_CHANNEL,
|
|
2385
|
+
DefaultDialogTemplateKeys,
|
|
2386
|
+
Dialog,
|
|
2387
|
+
DialogContent,
|
|
2388
|
+
DialogController,
|
|
2389
|
+
DialogHost,
|
|
1974
2390
|
Field,
|
|
1975
2391
|
HttpError,
|
|
2392
|
+
InfoDialog,
|
|
1976
2393
|
Input,
|
|
1977
2394
|
MockAuthHttpClient,
|
|
1978
2395
|
MockHttpClient,
|
|
@@ -1986,14 +2403,20 @@ export {
|
|
|
1986
2403
|
authController,
|
|
1987
2404
|
controllerFactory,
|
|
1988
2405
|
createAuthController,
|
|
2406
|
+
dialogController,
|
|
1989
2407
|
httpClient as fetchHttpClient,
|
|
2408
|
+
getDialogTemplate,
|
|
1990
2409
|
notifierController,
|
|
2410
|
+
registerDefaultDialogs,
|
|
2411
|
+
registerDialogTemplate,
|
|
1991
2412
|
resolveToastTheme,
|
|
1992
2413
|
ui,
|
|
2414
|
+
unregisterDialogTemplate,
|
|
1993
2415
|
useAuth,
|
|
1994
2416
|
useAuthActions,
|
|
1995
2417
|
useAuthController,
|
|
1996
2418
|
useAuthDispatch,
|
|
1997
2419
|
useAuthedUser,
|
|
2420
|
+
useDialog,
|
|
1998
2421
|
useResponsiveMutation
|
|
1999
2422
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hexdspace/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -71,6 +71,8 @@
|
|
|
71
71
|
"build": "tsup src/index.ts --dts --format esm --clean && pnpm run build:css",
|
|
72
72
|
"build:css": "mkdir -p dist/css && cp -R src/ui/theme/css/* dist/css/",
|
|
73
73
|
"test": "vitest",
|
|
74
|
+
"test:unit": "vitest --project unit",
|
|
75
|
+
"test:storybook": "vitest --project storybook",
|
|
74
76
|
"storybook": "storybook dev -p 6006",
|
|
75
77
|
"build-storybook": "storybook build"
|
|
76
78
|
}
|