@schemavaults/ui 0.75.0 → 0.77.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.
@@ -82,6 +82,8 @@ export * from "./description-list";
82
82
  export type * from "./description-list";
83
83
  export * from "./status-blinker";
84
84
  export type * from "./status-blinker";
85
+ export * from "./presence-indicator";
86
+ export type * from "./presence-indicator";
85
87
  export * from "./context-menu";
86
88
  export type * from "./context-menu";
87
89
  export * from "./inline-menu";
@@ -202,3 +204,5 @@ export * from "./http-method-badge";
202
204
  export type * from "./http-method-badge";
203
205
  export * from "./browser-frame";
204
206
  export type * from "./browser-frame";
207
+ export * from "./inline-edit";
208
+ export type * from "./inline-edit";
@@ -40,6 +40,7 @@ export * from "./skeleton";
40
40
  export * from "./key-value-with-skeleton";
41
41
  export * from "./description-list";
42
42
  export * from "./status-blinker";
43
+ export * from "./presence-indicator";
43
44
  export * from "./context-menu";
44
45
  export * from "./inline-menu";
45
46
  export * from "./stepper";
@@ -100,4 +101,5 @@ export * from "./time-picker";
100
101
  export * from "./mark";
101
102
  export * from "./http-method-badge";
102
103
  export * from "./browser-frame";
104
+ export * from "./inline-edit";
103
105
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { InlineEdit, InlineEdit as default, inlineEditDisplayVariants, inlineEditInputVariants, } from "./inline-edit";
2
+ export type { InlineEditCommitTrigger, InlineEditProps, } from "./inline-edit";
3
+ export { inlineEditSizeIds, inlineEditVariantIds, } from "./inline-edit-variants";
4
+ export type { InlineEditSize, InlineEditVariant, } from "./inline-edit-variants";
@@ -0,0 +1,3 @@
1
+ export { InlineEdit, InlineEdit as default, inlineEditDisplayVariants, inlineEditInputVariants, } from "./inline-edit";
2
+ export { inlineEditSizeIds, inlineEditVariantIds, } from "./inline-edit-variants";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ui/inline-edit/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,UAAU,IAAI,OAAO,EACrB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AAKvB,OAAO,EACL,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const inlineEditVariantIds: readonly ["default", "ghost", "underline"];
2
+ export type InlineEditVariant = (typeof inlineEditVariantIds)[number];
3
+ export declare const inlineEditSizeIds: readonly ["sm", "default", "lg"];
4
+ export type InlineEditSize = (typeof inlineEditSizeIds)[number];
@@ -0,0 +1,11 @@
1
+ export const inlineEditVariantIds = [
2
+ "default",
3
+ "ghost",
4
+ "underline",
5
+ ];
6
+ export const inlineEditSizeIds = [
7
+ "sm",
8
+ "default",
9
+ "lg",
10
+ ];
11
+ //# sourceMappingURL=inline-edit-variants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-edit-variants.js","sourceRoot":"","sources":["../../../../src/components/ui/inline-edit/inline-edit-variants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,SAAS;IACT,OAAO;IACP,WAAW;CACyB,CAAC;AAGvC,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI;IACJ,SAAS;IACT,IAAI;CACgC,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { type VariantProps } from "class-variance-authority";
2
+ import { type HTMLAttributes, type ReactElement, type ReactNode, type Ref } from "react";
3
+ import { inlineEditSizeIds, inlineEditVariantIds, type InlineEditSize, type InlineEditVariant } from "./inline-edit-variants";
4
+ declare const inlineEditDisplayVariants: (props?: ({
5
+ variant?: "default" | "underline" | "ghost" | null | undefined;
6
+ size?: "sm" | "default" | "lg" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ declare const inlineEditInputVariants: (props?: ({
9
+ size?: "sm" | "default" | "lg" | null | undefined;
10
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
+ export type InlineEditCommitTrigger = "enter" | "blur" | "button";
12
+ export interface InlineEditProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue" | "onBlur">, VariantProps<typeof inlineEditDisplayVariants> {
13
+ /** The current value to display. */
14
+ value: string;
15
+ /** Called when the user commits a new value (Enter, button, or blur). */
16
+ onValueChange?: (next: string, trigger: InlineEditCommitTrigger) => void;
17
+ /** Called when the user cancels editing (Escape or cancel button). */
18
+ onCancel?: (previous: string) => void;
19
+ /** Optional async save handler. When it rejects, the input stays in edit mode. */
20
+ onSave?: (next: string) => Promise<void> | void;
21
+ /** Placeholder shown when the value is empty. */
22
+ placeholder?: string;
23
+ /** Disables interaction; the value still renders. */
24
+ disabled?: boolean;
25
+ /** Use a multi-line textarea instead of a single-line input. */
26
+ multiline?: boolean;
27
+ /** Show explicit confirm/cancel buttons inside the editor. Defaults to true. */
28
+ showActions?: boolean;
29
+ /** Show a small pencil icon affordance next to the display value. Defaults to true. */
30
+ showEditIcon?: boolean;
31
+ /** Commit the value when the input loses focus. Defaults to true. */
32
+ commitOnBlur?: boolean;
33
+ /** Maximum length for the underlying input. */
34
+ maxLength?: number;
35
+ /** Accessible label for the underlying input. */
36
+ inputAriaLabel?: string;
37
+ /** Accessible label for the confirm button. */
38
+ confirmLabel?: string;
39
+ /** Accessible label for the cancel button. */
40
+ cancelLabel?: string;
41
+ /** Externally controlled error message. Skips committing and keeps edit mode open. */
42
+ error?: string | null;
43
+ /** Externally controlled loading state (e.g. when `onSave` is in flight). */
44
+ loading?: boolean;
45
+ /** Renders the editor open on first mount. */
46
+ defaultEditing?: boolean;
47
+ /** Optional ref forwarded to the outer wrapper. */
48
+ ref?: Ref<HTMLDivElement>;
49
+ /** Optional class names applied to the inner input/textarea element. */
50
+ inputClassName?: string;
51
+ /** Optional renderer for the display state. Receives the resolved label. */
52
+ renderDisplay?: (label: ReactNode, value: string) => ReactNode;
53
+ }
54
+ export declare function InlineEdit({ value, onValueChange, onCancel, onSave, placeholder, disabled, multiline, showActions, showEditIcon, commitOnBlur, maxLength, inputAriaLabel, confirmLabel, cancelLabel, error: externalError, loading: externalLoading, defaultEditing, variant, size, className, inputClassName, renderDisplay, ref, onClick, ...rest }: InlineEditProps): ReactElement;
55
+ export declare namespace InlineEdit {
56
+ var displayName: string;
57
+ }
58
+ export { inlineEditDisplayVariants, inlineEditInputVariants, inlineEditSizeIds, inlineEditVariantIds, };
59
+ export type { InlineEditSize, InlineEditVariant };
60
+ export default InlineEdit;
@@ -0,0 +1,208 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cva } from "class-variance-authority";
4
+ import { Check, Pencil, X } from "lucide-react";
5
+ import { useCallback, useEffect, useId, useLayoutEffect, useRef, useState, } from "react";
6
+ import { cn } from "../../../lib/utils";
7
+ import { inlineEditSizeIds, inlineEditVariantIds, } from "./inline-edit-variants";
8
+ const inlineEditDisplayVariants = cva("group/inline-edit inline-flex max-w-full items-center gap-1.5 rounded-md text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-60 data-[empty=true]:text-muted-foreground", {
9
+ variants: {
10
+ variant: {
11
+ default: "border border-transparent hover:border-input data-[interactive=true]:hover:bg-accent/40",
12
+ ghost: "border border-transparent data-[interactive=true]:hover:bg-accent/60",
13
+ underline: "rounded-none border-b border-dashed border-transparent data-[interactive=true]:hover:border-input data-[interactive=true]:hover:text-foreground",
14
+ },
15
+ size: {
16
+ sm: "min-h-7 px-1.5 py-0.5 text-xs",
17
+ default: "min-h-9 px-2 py-1 text-sm",
18
+ lg: "min-h-11 px-2.5 py-1.5 text-base",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ size: "default",
24
+ },
25
+ });
26
+ const inlineEditInputVariants = cva("w-full bg-transparent text-foreground placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60", {
27
+ variants: {
28
+ size: {
29
+ sm: "text-xs",
30
+ default: "text-sm",
31
+ lg: "text-base",
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ size: "default",
36
+ },
37
+ });
38
+ const inlineEditContainerVariants = cva("inline-flex max-w-full items-stretch gap-1 rounded-md bg-background ring-2 ring-ring ring-offset-2 ring-offset-background", {
39
+ variants: {
40
+ size: {
41
+ sm: "min-h-7 px-1.5 py-0.5",
42
+ default: "min-h-9 px-2 py-1",
43
+ lg: "min-h-11 px-2.5 py-1.5",
44
+ },
45
+ },
46
+ defaultVariants: {
47
+ size: "default",
48
+ },
49
+ });
50
+ const inlineEditActionButtonVariants = cva("inline-flex shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 data-[role=confirm]:text-emerald-600 data-[role=confirm]:hover:bg-emerald-500/10 data-[role=confirm]:hover:text-emerald-600 data-[role=cancel]:hover:bg-destructive/10 data-[role=cancel]:hover:text-destructive", {
51
+ variants: {
52
+ size: {
53
+ sm: "size-5 [&>svg]:size-3",
54
+ default: "size-6 [&>svg]:size-3.5",
55
+ lg: "size-7 [&>svg]:size-4",
56
+ },
57
+ },
58
+ defaultVariants: {
59
+ size: "default",
60
+ },
61
+ });
62
+ function isTextarea(el) {
63
+ return el?.tagName === "TEXTAREA";
64
+ }
65
+ export function InlineEdit({ value, onValueChange, onCancel, onSave, placeholder = "Click to edit", disabled = false, multiline = false, showActions = true, showEditIcon = true, commitOnBlur = true, maxLength, inputAriaLabel, confirmLabel = "Save", cancelLabel = "Cancel", error: externalError = null, loading: externalLoading = false, defaultEditing = false, variant, size, className, inputClassName, renderDisplay, ref, onClick, ...rest }) {
66
+ const [editing, setEditing] = useState(defaultEditing);
67
+ const [draft, setDraft] = useState(value);
68
+ const [internalLoading, setInternalLoading] = useState(false);
69
+ const [internalError, setInternalError] = useState(null);
70
+ const wasJustOpened = useRef(false);
71
+ const inputRef = useRef(null);
72
+ const reactId = useId();
73
+ const errorId = `${reactId}-error`;
74
+ const isLoading = externalLoading || internalLoading;
75
+ const errorMessage = externalError ?? internalError;
76
+ const hasError = errorMessage !== null && errorMessage !== "";
77
+ useEffect(() => {
78
+ if (!editing)
79
+ setDraft(value);
80
+ }, [value, editing]);
81
+ useLayoutEffect(() => {
82
+ if (!editing)
83
+ return;
84
+ const el = inputRef.current;
85
+ if (el === null)
86
+ return;
87
+ if (wasJustOpened.current) {
88
+ wasJustOpened.current = false;
89
+ el.focus();
90
+ try {
91
+ const length = el.value.length;
92
+ el.setSelectionRange(length, length);
93
+ }
94
+ catch {
95
+ // setSelectionRange is unsupported on some input types; ignore.
96
+ }
97
+ }
98
+ if (isTextarea(el)) {
99
+ el.style.height = "auto";
100
+ el.style.height = `${el.scrollHeight}px`;
101
+ }
102
+ }, [editing, draft]);
103
+ const openEditor = useCallback(() => {
104
+ if (disabled)
105
+ return;
106
+ wasJustOpened.current = true;
107
+ setDraft(value);
108
+ setInternalError(null);
109
+ setEditing(true);
110
+ }, [disabled, value]);
111
+ const closeEditor = useCallback(() => {
112
+ setEditing(false);
113
+ setInternalError(null);
114
+ }, []);
115
+ const commit = useCallback(async (trigger) => {
116
+ if (isLoading)
117
+ return;
118
+ const next = draft;
119
+ if (next === value) {
120
+ closeEditor();
121
+ return;
122
+ }
123
+ if (onSave === undefined) {
124
+ onValueChange?.(next, trigger);
125
+ closeEditor();
126
+ return;
127
+ }
128
+ setInternalLoading(true);
129
+ try {
130
+ await onSave(next);
131
+ onValueChange?.(next, trigger);
132
+ closeEditor();
133
+ }
134
+ catch (err) {
135
+ const message = err instanceof Error ? err.message : "Failed to save value";
136
+ setInternalError(message);
137
+ }
138
+ finally {
139
+ setInternalLoading(false);
140
+ }
141
+ }, [closeEditor, draft, isLoading, onSave, onValueChange, value]);
142
+ const cancel = useCallback(() => {
143
+ if (isLoading)
144
+ return;
145
+ setDraft(value);
146
+ onCancel?.(value);
147
+ closeEditor();
148
+ }, [closeEditor, isLoading, onCancel, value]);
149
+ const handleChange = (event) => {
150
+ setDraft(event.target.value);
151
+ if (internalError !== null)
152
+ setInternalError(null);
153
+ };
154
+ const handleKeyDown = (event) => {
155
+ if (event.key === "Escape") {
156
+ event.preventDefault();
157
+ cancel();
158
+ return;
159
+ }
160
+ if (event.key === "Enter") {
161
+ if (multiline && !(event.metaKey || event.ctrlKey))
162
+ return;
163
+ event.preventDefault();
164
+ void commit("enter");
165
+ }
166
+ };
167
+ const handleBlur = (event) => {
168
+ if (!commitOnBlur)
169
+ return;
170
+ const next = event.relatedTarget;
171
+ const root = event.currentTarget.closest("[data-slot=inline-edit-editor]");
172
+ if (next !== null && root !== null && root.contains(next))
173
+ return;
174
+ void commit("blur");
175
+ };
176
+ const handleDisplayKeyDown = (event) => {
177
+ if (disabled)
178
+ return;
179
+ if (event.key === "Enter" || event.key === " " || event.key === "F2") {
180
+ event.preventDefault();
181
+ openEditor();
182
+ }
183
+ };
184
+ const isEmpty = value.length === 0;
185
+ const displayLabel = isEmpty ? placeholder : value;
186
+ if (editing) {
187
+ return (_jsxs("div", { ref: ref, "data-slot": "inline-edit", "data-state": "editing", className: cn("inline-flex max-w-full flex-col gap-1", className), ...rest, children: [_jsxs("div", { "data-slot": "inline-edit-editor", className: cn(inlineEditContainerVariants({ size }), hasError && "ring-destructive", isLoading && "opacity-80"), children: [multiline ? (_jsx("textarea", { ref: (el) => {
188
+ inputRef.current = el;
189
+ }, "data-slot": "inline-edit-input", value: draft, disabled: isLoading, maxLength: maxLength, "aria-label": inputAriaLabel, "aria-invalid": hasError || undefined, "aria-describedby": hasError ? errorId : undefined, onChange: handleChange, onKeyDown: handleKeyDown, onBlur: handleBlur, rows: 1, className: cn(inlineEditInputVariants({ size }), "resize-none overflow-hidden", inputClassName) })) : (_jsx("input", { ref: (el) => {
190
+ inputRef.current = el;
191
+ }, type: "text", "data-slot": "inline-edit-input", value: draft, disabled: isLoading, maxLength: maxLength, "aria-label": inputAriaLabel, "aria-invalid": hasError || undefined, "aria-describedby": hasError ? errorId : undefined, onChange: handleChange, onKeyDown: handleKeyDown, onBlur: handleBlur, className: cn(inlineEditInputVariants({ size }), inputClassName) })), showActions && (_jsxs("div", { "data-slot": "inline-edit-actions", className: "inline-flex shrink-0 items-center gap-0.5", children: [_jsx("button", { type: "button", "data-role": "cancel", "data-slot": "inline-edit-cancel", "aria-label": cancelLabel, disabled: isLoading, onClick: cancel, className: cn(inlineEditActionButtonVariants({ size })), children: _jsx(X, { "aria-hidden": "true" }) }), _jsx("button", { type: "button", "data-role": "confirm", "data-slot": "inline-edit-confirm", "aria-label": confirmLabel, disabled: isLoading, onClick: () => {
192
+ void commit("button");
193
+ }, className: cn(inlineEditActionButtonVariants({ size })), children: _jsx(Check, { "aria-hidden": "true" }) })] }))] }), hasError && (_jsx("span", { id: errorId, "data-slot": "inline-edit-error", role: "alert", className: "text-xs text-destructive", children: errorMessage }))] }));
194
+ }
195
+ return (_jsxs("button", { ref: ref, type: "button", "data-slot": "inline-edit", "data-state": "idle", "data-empty": isEmpty || undefined, "data-disabled": disabled || undefined, "data-interactive": !disabled || undefined, "aria-label": inputAriaLabel, disabled: disabled, onClick: (event) => {
196
+ onClick?.(event);
197
+ if (event.defaultPrevented)
198
+ return;
199
+ openEditor();
200
+ }, onKeyDown: handleDisplayKeyDown, className: cn(inlineEditDisplayVariants({ variant, size }), "cursor-text text-left", className), ...rest, children: [_jsx("span", { "data-slot": "inline-edit-label", className: cn("min-w-0 flex-1 truncate", multiline && "whitespace-pre-wrap break-words"), children: renderDisplay !== undefined
201
+ ? renderDisplay(displayLabel, value)
202
+ : displayLabel }), showEditIcon && !disabled && (_jsx(Pencil, { "aria-hidden": "true", "data-slot": "inline-edit-icon", className: cn("shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover/inline-edit:opacity-100 group-focus-visible/inline-edit:opacity-100", size === "sm" && "size-3", (size === "default" || size === undefined || size === null) &&
203
+ "size-3.5", size === "lg" && "size-4") }))] }));
204
+ }
205
+ InlineEdit.displayName = "InlineEdit";
206
+ export { inlineEditDisplayVariants, inlineEditInputVariants, inlineEditSizeIds, inlineEditVariantIds, };
207
+ export default InlineEdit;
208
+ //# sourceMappingURL=inline-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-edit.js","sourceRoot":"","sources":["../../../../src/components/ui/inline-edit/inline-edit.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { PresenceIndicator, PresenceIndicator as default, presenceStatusIds, presenceSizeIds, } from "./presence-indicator";
2
+ export type { PresenceIndicatorProps, PresenceStatusId, PresenceSizeId, } from "./presence-indicator";
@@ -0,0 +1,2 @@
1
+ export { PresenceIndicator, PresenceIndicator as default, presenceStatusIds, presenceSizeIds, } from "./presence-indicator";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ui/presence-indicator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,IAAI,OAAO,EAC5B,iBAAiB,EACjB,eAAe,GAChB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { HTMLAttributes, ReactElement, Ref } from "react";
2
+ export declare const presenceStatusIds: readonly ["online", "idle", "busy", "away", "dnd", "offline", "invisible"];
3
+ export type PresenceStatusId = (typeof presenceStatusIds)[number];
4
+ export declare const presenceSizeIds: readonly ["xs", "sm", "md", "lg", "xl"];
5
+ export type PresenceSizeId = (typeof presenceSizeIds)[number];
6
+ export interface PresenceIndicatorProps extends Omit<HTMLAttributes<HTMLSpanElement>, "children" | "aria-label"> {
7
+ /** Semantic presence status. Defaults to `"online"`. */
8
+ status?: PresenceStatusId;
9
+ /** Visual size of the dot. Defaults to `"md"`. */
10
+ size?: PresenceSizeId;
11
+ /** Render a soft `ping` animation around the dot. */
12
+ pulse?: boolean;
13
+ /**
14
+ * Render a contrasting ring around the dot. Useful when overlaying the
15
+ * indicator on top of an `Avatar` or coloured surface.
16
+ */
17
+ bordered?: boolean;
18
+ /**
19
+ * Render a text label next to the dot. Pass `true` to use the default
20
+ * status label (e.g. `"Online"`), or a string for a custom one.
21
+ */
22
+ label?: boolean | string;
23
+ /**
24
+ * Accessible label describing the status. Defaults to a humanised version of
25
+ * the `status` (e.g. `"Online"`). Set to `null` to mark the indicator as
26
+ * purely decorative (e.g. when paired with adjacent text that already
27
+ * conveys the status).
28
+ */
29
+ "aria-label"?: string | null;
30
+ ref?: Ref<HTMLSpanElement>;
31
+ }
32
+ declare function PresenceIndicator({ className, status, size, pulse, bordered, label, ref, "aria-label": ariaLabelProp, ...rest }: PresenceIndicatorProps): ReactElement;
33
+ declare namespace PresenceIndicator {
34
+ var displayName: string;
35
+ }
36
+ export { PresenceIndicator };
@@ -0,0 +1,95 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cn } from "../../../lib/utils";
4
+ export const presenceStatusIds = [
5
+ "online",
6
+ "idle",
7
+ "busy",
8
+ "away",
9
+ "dnd",
10
+ "offline",
11
+ "invisible",
12
+ ];
13
+ export const presenceSizeIds = [
14
+ "xs",
15
+ "sm",
16
+ "md",
17
+ "lg",
18
+ "xl",
19
+ ];
20
+ const dotColorClasses = {
21
+ online: "bg-green-500",
22
+ idle: "bg-yellow-400",
23
+ busy: "bg-orange-500",
24
+ away: "bg-amber-500",
25
+ dnd: "bg-destructive",
26
+ offline: "bg-muted-foreground/50",
27
+ invisible: "bg-transparent border border-muted-foreground/60",
28
+ };
29
+ const dotSizeClasses = {
30
+ xs: "h-1.5 w-1.5",
31
+ sm: "h-2 w-2",
32
+ md: "h-2.5 w-2.5",
33
+ lg: "h-3 w-3",
34
+ xl: "h-3.5 w-3.5",
35
+ };
36
+ const dndBarSizeClasses = {
37
+ xs: "h-px w-[60%]",
38
+ sm: "h-px w-[60%]",
39
+ md: "h-px w-[60%]",
40
+ lg: "h-[1.5px] w-[60%]",
41
+ xl: "h-[1.5px] w-[60%]",
42
+ };
43
+ const ringSizeClasses = {
44
+ xs: "ring-[1.5px]",
45
+ sm: "ring-2",
46
+ md: "ring-2",
47
+ lg: "ring-2",
48
+ xl: "ring-[2.5px]",
49
+ };
50
+ const labelTextClasses = {
51
+ xs: "text-[10px]",
52
+ sm: "text-xs",
53
+ md: "text-xs",
54
+ lg: "text-sm",
55
+ xl: "text-sm",
56
+ };
57
+ const statusLabels = {
58
+ online: "Online",
59
+ idle: "Idle",
60
+ busy: "Busy",
61
+ away: "Away",
62
+ dnd: "Do not disturb",
63
+ offline: "Offline",
64
+ invisible: "Invisible",
65
+ };
66
+ const pulseColorClasses = {
67
+ online: "bg-green-500",
68
+ idle: "bg-yellow-400",
69
+ busy: "bg-orange-500",
70
+ away: "bg-amber-500",
71
+ dnd: "bg-destructive",
72
+ offline: "bg-muted-foreground/50",
73
+ invisible: "bg-muted-foreground/40",
74
+ };
75
+ function PresenceDot({ status, size, pulse, bordered, }) {
76
+ return (_jsxs("span", { className: "relative inline-flex items-center justify-center", children: [pulse ? (_jsx("span", { "aria-hidden": "true", className: cn("absolute inline-flex h-full w-full rounded-full opacity-75 animate-ping", pulseColorClasses[status], dotSizeClasses[size]) })) : null, _jsx("span", { "data-slot": "presence-indicator-dot", className: cn("relative inline-flex items-center justify-center rounded-full", dotColorClasses[status], dotSizeClasses[size], bordered && cn(ringSizeClasses[size], "ring-background")), children: status === "dnd" ? (_jsx("span", { "aria-hidden": "true", className: cn("block rounded-full bg-destructive-foreground", dndBarSizeClasses[size]) })) : null })] }));
77
+ }
78
+ function PresenceIndicator({ className, status = "online", size = "md", pulse = false, bordered = false, label, ref, "aria-label": ariaLabelProp, ...rest }) {
79
+ const decorative = ariaLabelProp === null;
80
+ const ariaLabel = decorative
81
+ ? undefined
82
+ : (ariaLabelProp ?? statusLabels[status]);
83
+ const labelText = label === true
84
+ ? statusLabels[status]
85
+ : typeof label === "string"
86
+ ? label
87
+ : null;
88
+ if (labelText !== null) {
89
+ return (_jsxs("span", { ref: ref, "data-slot": "presence-indicator", "data-status": status, role: decorative ? undefined : "status", "aria-label": ariaLabel, "aria-hidden": decorative ? true : undefined, className: cn("inline-flex items-center gap-1.5 text-foreground", className), ...rest, children: [_jsx(PresenceDot, { status: status, size: size, pulse: pulse, bordered: bordered }), _jsx("span", { className: cn("font-medium leading-none", labelTextClasses[size]), children: labelText })] }));
90
+ }
91
+ return (_jsx("span", { ref: ref, "data-slot": "presence-indicator", "data-status": status, role: decorative ? undefined : "status", "aria-label": ariaLabel, "aria-hidden": decorative ? true : undefined, className: cn("inline-flex shrink-0 items-center justify-center", className), ...rest, children: _jsx(PresenceDot, { status: status, size: size, pulse: pulse, bordered: bordered }) }));
92
+ }
93
+ PresenceIndicator.displayName = "PresenceIndicator";
94
+ export { PresenceIndicator };
95
+ //# sourceMappingURL=presence-indicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence-indicator.js","sourceRoot":"","sources":["../../../../src/components/ui/presence-indicator/presence-indicator.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schemavaults/ui",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "description": "React.js UI components for SchemaVaults frontend applications",