@civitai/blocks-react 0.11.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -3
- package/dist/internal/liveHost.d.ts.map +1 -1
- package/dist/internal/liveHost.js +73 -10
- package/dist/internal/liveHost.js.map +1 -1
- package/dist/ui/Alert.d.ts +19 -0
- package/dist/ui/Alert.d.ts.map +1 -0
- package/dist/ui/Alert.js +12 -0
- package/dist/ui/Alert.js.map +1 -0
- package/dist/ui/Badge.d.ts +18 -0
- package/dist/ui/Badge.d.ts.map +1 -0
- package/dist/ui/Badge.js +25 -0
- package/dist/ui/Badge.js.map +1 -0
- package/dist/ui/Button.d.ts +35 -0
- package/dist/ui/Button.d.ts.map +1 -0
- package/dist/ui/Button.js +44 -0
- package/dist/ui/Button.js.map +1 -0
- package/dist/ui/Card.d.ts +14 -0
- package/dist/ui/Card.d.ts.map +1 -0
- package/dist/ui/Card.js +11 -0
- package/dist/ui/Card.js.map +1 -0
- package/dist/ui/Group.d.ts +15 -0
- package/dist/ui/Group.d.ts.map +1 -0
- package/dist/ui/Group.js +22 -0
- package/dist/ui/Group.js.map +1 -0
- package/dist/ui/Loader.d.ts +18 -0
- package/dist/ui/Loader.d.ts.map +1 -0
- package/dist/ui/Loader.js +14 -0
- package/dist/ui/Loader.js.map +1 -0
- package/dist/ui/Modal.d.ts +46 -0
- package/dist/ui/Modal.d.ts.map +1 -0
- package/dist/ui/Modal.js +67 -0
- package/dist/ui/Modal.js.map +1 -0
- package/dist/ui/Stack.d.ts +13 -0
- package/dist/ui/Stack.d.ts.map +1 -0
- package/dist/ui/Stack.js +21 -0
- package/dist/ui/Stack.js.map +1 -0
- package/dist/ui/TextInput.d.ts +26 -0
- package/dist/ui/TextInput.d.ts.map +1 -0
- package/dist/ui/TextInput.js +23 -0
- package/dist/ui/TextInput.js.map +1 -0
- package/dist/ui/Textarea.d.ts +32 -0
- package/dist/ui/Textarea.d.ts.map +1 -0
- package/dist/ui/Textarea.js +23 -0
- package/dist/ui/Textarea.js.map +1 -0
- package/dist/ui/index.d.ts +33 -4
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +26 -4
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/styles.d.ts +19 -0
- package/dist/ui/styles.d.ts.map +1 -0
- package/dist/ui/styles.js +416 -0
- package/dist/ui/styles.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { useBlocksStyles } from './styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* A CSS-keyframe spinner. Headless, auto-themed. Reused by `<Button loading>`.
|
|
6
|
+
*
|
|
7
|
+
* Carries `role="status"` + an accessible label so screen readers announce a
|
|
8
|
+
* busy state; pass `aria-label` to override the default "Loading".
|
|
9
|
+
*/
|
|
10
|
+
export const Loader = forwardRef(function Loader({ size = 'md', color, style, ...rest }, ref) {
|
|
11
|
+
useBlocksStyles();
|
|
12
|
+
return (_jsx("span", { ref: ref, ...rest, "data-civitai-ui": "loader", "data-size": size, role: "status", "aria-label": rest['aria-label'] ?? 'Loading', style: color ? { color, ...style } : style }));
|
|
13
|
+
});
|
|
14
|
+
//# sourceMappingURL=Loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Loader.js","sourceRoot":"","sources":["../../src/ui/Loader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAe9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAA+B,SAAS,MAAM,CAC5E,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EACtC,GAAG;IAEH,eAAe,EAAE,CAAC;IAClB,OAAO,CACL,eACE,GAAG,EAAE,GAAG,KACJ,IAAI,qBACQ,QAAQ,eACb,IAAI,EACf,IAAI,EAAC,QAAQ,gBAGD,IAAI,CAAC,YAAY,CAAC,IAAI,SAAS,EAC3C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,GAC1C,CACH,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type ModalSize = 'sm' | 'md' | 'lg';
|
|
2
|
+
export interface ModalProps {
|
|
3
|
+
/** Whether the modal is shown. When `false`, nothing is rendered. */
|
|
4
|
+
opened: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Called when the user requests close — Escape, overlay click, or the
|
|
7
|
+
* header close button. The parent owns `opened`, so it must flip it.
|
|
8
|
+
*/
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
/** Optional header title (also wires `aria-labelledby`). */
|
|
11
|
+
title?: React.ReactNode;
|
|
12
|
+
/** Panel width preset. Defaults to `'md'`. */
|
|
13
|
+
size?: ModalSize;
|
|
14
|
+
/** Show the header close (×) button. Defaults to `true`. */
|
|
15
|
+
withCloseButton?: boolean;
|
|
16
|
+
/** Close when the dimmed overlay (outside the panel) is clicked. Default `true`. */
|
|
17
|
+
closeOnOverlayClick?: boolean;
|
|
18
|
+
/** Close when Escape is pressed. Default `true`. */
|
|
19
|
+
closeOnEscape?: boolean;
|
|
20
|
+
/** Accessible label for the close button. Defaults to "Close". */
|
|
21
|
+
closeButtonLabel?: string;
|
|
22
|
+
/** Class applied to the panel element. */
|
|
23
|
+
className?: string;
|
|
24
|
+
/** Style applied to the panel element. */
|
|
25
|
+
style?: React.CSSProperties;
|
|
26
|
+
/** Modal body content. */
|
|
27
|
+
children?: React.ReactNode;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A lightweight modal dialog.
|
|
31
|
+
*
|
|
32
|
+
* `position: fixed` overlay covers the iframe viewport — correct here, since
|
|
33
|
+
* the iframe IS the block's surface (no host bleed-through to worry about).
|
|
34
|
+
*
|
|
35
|
+
* Accessibility: `role="dialog"` + `aria-modal="true"`, `aria-labelledby` when
|
|
36
|
+
* a `title` is given. On open the panel is focused and the previously-focused
|
|
37
|
+
* element is restored on close. Escape and overlay-click both call `onClose`;
|
|
38
|
+
* a click inside the panel does NOT.
|
|
39
|
+
*
|
|
40
|
+
* v0 limitation (documented): this does NOT trap focus inside the panel — Tab
|
|
41
|
+
* can still reach content behind the overlay. Sufficient for a simple
|
|
42
|
+
* confirm/settings dialog inside the sandboxed block; a full focus-trap is a
|
|
43
|
+
* v1 follow-up (kept dependency-free here on purpose).
|
|
44
|
+
*/
|
|
45
|
+
export declare function Modal(props: ModalProps): React.JSX.Element | null;
|
|
46
|
+
//# sourceMappingURL=Modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../src/ui/Modal.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,4DAA4D;IAC5D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oFAAoF;IACpF,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oDAAoD;IACpD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAmGjE"}
|
package/dist/ui/Modal.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useRef } from 'react';
|
|
3
|
+
import { useBlocksStyles } from './styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* A lightweight modal dialog.
|
|
6
|
+
*
|
|
7
|
+
* `position: fixed` overlay covers the iframe viewport — correct here, since
|
|
8
|
+
* the iframe IS the block's surface (no host bleed-through to worry about).
|
|
9
|
+
*
|
|
10
|
+
* Accessibility: `role="dialog"` + `aria-modal="true"`, `aria-labelledby` when
|
|
11
|
+
* a `title` is given. On open the panel is focused and the previously-focused
|
|
12
|
+
* element is restored on close. Escape and overlay-click both call `onClose`;
|
|
13
|
+
* a click inside the panel does NOT.
|
|
14
|
+
*
|
|
15
|
+
* v0 limitation (documented): this does NOT trap focus inside the panel — Tab
|
|
16
|
+
* can still reach content behind the overlay. Sufficient for a simple
|
|
17
|
+
* confirm/settings dialog inside the sandboxed block; a full focus-trap is a
|
|
18
|
+
* v1 follow-up (kept dependency-free here on purpose).
|
|
19
|
+
*/
|
|
20
|
+
export function Modal(props) {
|
|
21
|
+
const { opened, onClose, title, size = 'md', withCloseButton = true, closeOnOverlayClick = true, closeOnEscape = true, closeButtonLabel = 'Close', className, style, children, } = props;
|
|
22
|
+
useBlocksStyles();
|
|
23
|
+
const panelRef = useRef(null);
|
|
24
|
+
const previouslyFocused = useRef(null);
|
|
25
|
+
const reactId = useId();
|
|
26
|
+
const titleId = `ci-modal-title-${reactId}`;
|
|
27
|
+
// Focus the panel on open; restore focus to the prior element on close.
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!opened)
|
|
30
|
+
return;
|
|
31
|
+
previouslyFocused.current =
|
|
32
|
+
typeof document !== 'undefined' ? document.activeElement : null;
|
|
33
|
+
// Focus after paint so the element exists and is focusable.
|
|
34
|
+
panelRef.current?.focus();
|
|
35
|
+
return () => {
|
|
36
|
+
const prev = previouslyFocused.current;
|
|
37
|
+
if (prev instanceof HTMLElement)
|
|
38
|
+
prev.focus();
|
|
39
|
+
};
|
|
40
|
+
}, [opened]);
|
|
41
|
+
// Escape-to-close. Listener only attached while open.
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!opened || !closeOnEscape)
|
|
44
|
+
return;
|
|
45
|
+
const onKeyDown = (e) => {
|
|
46
|
+
if (e.key === 'Escape') {
|
|
47
|
+
// Don't stopPropagation — that swallows Escape unpredictably when two
|
|
48
|
+
// modals (or an author's own document Escape handler) are present. v0
|
|
49
|
+
// assumes a single modal, so letting the event continue is correct.
|
|
50
|
+
onClose();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
document.addEventListener('keydown', onKeyDown);
|
|
54
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
55
|
+
}, [opened, closeOnEscape, onClose]);
|
|
56
|
+
if (!opened)
|
|
57
|
+
return null;
|
|
58
|
+
return (_jsx("div", { "data-civitai-ui": "modal-overlay", onMouseDown: (e) => {
|
|
59
|
+
// Only close on a click that starts AND lands on the overlay itself —
|
|
60
|
+
// a drag that began inside the panel and released on the overlay must
|
|
61
|
+
// not close it.
|
|
62
|
+
if (closeOnOverlayClick && e.target === e.currentTarget) {
|
|
63
|
+
onClose();
|
|
64
|
+
}
|
|
65
|
+
}, children: _jsxs("div", { ref: panelRef, className: className, "data-civitai-ui": "modal", "data-size": size, role: "dialog", "aria-modal": "true", "aria-labelledby": title != null ? titleId : undefined, tabIndex: -1, style: style, children: [title != null || withCloseButton ? (_jsxs("div", { "data-civitai-ui-modal-header": true, children: [title != null ? (_jsx("h2", { id: titleId, "data-civitai-ui-modal-title": true, children: title })) : (_jsx("span", {})), withCloseButton ? (_jsx("button", { type: "button", "data-civitai-ui-modal-close": true, "aria-label": closeButtonLabel, onClick: () => onClose(), children: "\u00D7" })) : null] })) : null, _jsx("div", { "data-civitai-ui-modal-body": true, children: children })] }) }));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=Modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../src/ui/Modal.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface StackProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
2
|
+
/** Gap between children (any CSS length, or a number → px). Defaults to 12. */
|
|
3
|
+
gap?: string | number;
|
|
4
|
+
/** `align-items` value. */
|
|
5
|
+
align?: React.CSSProperties['alignItems'];
|
|
6
|
+
/** `justify-content` value. */
|
|
7
|
+
justify?: React.CSSProperties['justifyContent'];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Vertical flex container. Wraps a `<div>` (ref-forwarded). Auto-themed.
|
|
11
|
+
*/
|
|
12
|
+
export declare const Stack: import("react").ForwardRefExoticComponent<StackProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
13
|
+
//# sourceMappingURL=Stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../src/ui/Stack.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACtE,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC1C,+BAA+B;IAC/B,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;CACjD;AAOD;;GAEG;AACH,eAAO,MAAM,KAAK,uGAoBhB,CAAC"}
|
package/dist/ui/Stack.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from 'react';
|
|
3
|
+
import { useBlocksStyles } from './styles.js';
|
|
4
|
+
function toLength(v) {
|
|
5
|
+
if (v == null)
|
|
6
|
+
return undefined;
|
|
7
|
+
return typeof v === 'number' ? `${v}px` : v;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Vertical flex container. Wraps a `<div>` (ref-forwarded). Auto-themed.
|
|
11
|
+
*/
|
|
12
|
+
export const Stack = forwardRef(function Stack({ gap = 12, align, justify, style, children, ...rest }, ref) {
|
|
13
|
+
useBlocksStyles();
|
|
14
|
+
return (_jsx("div", { ref: ref, ...rest, "data-civitai-ui": "stack", style: {
|
|
15
|
+
gap: toLength(gap),
|
|
16
|
+
alignItems: align,
|
|
17
|
+
justifyContent: justify,
|
|
18
|
+
...style,
|
|
19
|
+
}, children: children }));
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=Stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Stack.js","sourceRoot":"","sources":["../../src/ui/Stack.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAW9C,SAAS,QAAQ,CAAC,CAA8B;IAC9C,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,SAAS,CAAC;IAChC,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA6B,SAAS,KAAK,CACxE,EAAE,GAAG,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EACtD,GAAG;IAEH,eAAe,EAAE,CAAC;IAClB,OAAO,CACL,cACE,GAAG,EAAE,GAAG,KACJ,IAAI,qBACQ,OAAO,EACvB,KAAK,EAAE;YACL,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC;YAClB,UAAU,EAAE,KAAK;YACjB,cAAc,EAAE,OAAO;YACvB,GAAG,KAAK;SACT,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface TextInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
2
|
+
/** Visible field label, rendered in a `<label>` linked to the input. */
|
|
3
|
+
label?: React.ReactNode;
|
|
4
|
+
/** Helper text under the label, linked via `aria-describedby`. */
|
|
5
|
+
description?: React.ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Error message. When set, the input gets `aria-invalid="true"`, the message
|
|
8
|
+
* is announced (`role="alert"`) and linked via `aria-describedby`.
|
|
9
|
+
*/
|
|
10
|
+
error?: React.ReactNode;
|
|
11
|
+
/** Mark required: shows an asterisk and sets the native `required`. */
|
|
12
|
+
required?: boolean;
|
|
13
|
+
/** Class on the wrapping element (the `<input>` is `inputClassName`). */
|
|
14
|
+
className?: string;
|
|
15
|
+
/** Class applied to the native `<input>`. */
|
|
16
|
+
inputClassName?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Labeled text input. Wraps a native `<input>` (ref-forwarded). The label,
|
|
20
|
+
* description and error are wired to the control via `htmlFor` / `id` /
|
|
21
|
+
* `aria-describedby` / `aria-invalid` so the field is announced correctly.
|
|
22
|
+
*
|
|
23
|
+
* Auto-themed via `useBlocksStyles()`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const TextInput: import("react").ForwardRefExoticComponent<TextInputProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
26
|
+
//# sourceMappingURL=TextInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextInput.d.ts","sourceRoot":"","sources":["../../src/ui/TextInput.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACjE,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,kEAAkE;IAClE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,6GAmErB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId } from 'react';
|
|
3
|
+
import { useBlocksStyles } from './styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* Labeled text input. Wraps a native `<input>` (ref-forwarded). The label,
|
|
6
|
+
* description and error are wired to the control via `htmlFor` / `id` /
|
|
7
|
+
* `aria-describedby` / `aria-invalid` so the field is announced correctly.
|
|
8
|
+
*
|
|
9
|
+
* Auto-themed via `useBlocksStyles()`.
|
|
10
|
+
*/
|
|
11
|
+
export const TextInput = forwardRef(function TextInput({ label, description, error, required, className, inputClassName, id, style, ...rest }, ref) {
|
|
12
|
+
useBlocksStyles();
|
|
13
|
+
const reactId = useId();
|
|
14
|
+
const inputId = id ?? `ci-input-${reactId}`;
|
|
15
|
+
const descId = `${inputId}-desc`;
|
|
16
|
+
const errId = `${inputId}-err`;
|
|
17
|
+
const hasError = error != null && error !== false;
|
|
18
|
+
const describedBy = [description != null ? descId : null, hasError ? errId : null]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(' ') || undefined;
|
|
21
|
+
return (_jsxs("div", { className: className, "data-civitai-ui": "text-input", "data-invalid": hasError ? 'true' : undefined, style: style, children: [label != null ? (_jsxs("label", { htmlFor: inputId, "data-civitai-ui-label": true, children: [label, required ? (_jsx("span", { "data-civitai-ui-required": true, "aria-hidden": "true", children: "*" })) : null] })) : null, description != null ? (_jsx("span", { id: descId, "data-civitai-ui-description": true, children: description })) : null, _jsx("input", { ref: ref, ...rest, id: inputId, className: inputClassName, "data-civitai-ui-control": true, required: required, "aria-invalid": hasError || undefined, "aria-describedby": describedBy, "aria-required": required || undefined }), hasError ? (_jsx("span", { id: errId, "data-civitai-ui-error": true, role: "alert", children: error })) : null] }));
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=TextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextInput.js","sourceRoot":"","sources":["../../src/ui/TextInput.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAqB9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CACjC,SAAS,SAAS,CAChB,EACE,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,EAAE,EACF,KAAK,EACL,GAAG,IAAI,EACR,EACD,GAAG;IAEH,eAAe,EAAE,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,EAAE,IAAI,YAAY,OAAO,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC;IACjC,MAAM,KAAK,GAAG,GAAG,OAAO,MAAM,CAAC;IAC/B,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC;IAClD,MAAM,WAAW,GACf,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;SAC3D,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAE5B,OAAO,CACL,eACE,SAAS,EAAE,SAAS,qBACJ,YAAY,kBACd,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAC3C,KAAK,EAAE,KAAK,aAEX,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CACf,iBAAO,OAAO,EAAE,OAAO,4CACpB,KAAK,EACL,QAAQ,CAAC,CAAC,CAAC,CACV,gEAA2C,MAAM,kBAE1C,CACR,CAAC,CAAC,CAAC,IAAI,IACF,CACT,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CACrB,eAAM,EAAE,EAAE,MAAM,iDACb,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,EACR,gBACE,GAAG,EAAE,GAAG,KACJ,IAAI,EACR,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,cAAc,mCAEzB,QAAQ,EAAE,QAAQ,kBACJ,QAAQ,IAAI,SAAS,sBACjB,WAAW,mBACd,QAAQ,IAAI,SAAS,GACpC,EACD,QAAQ,CAAC,CAAC,CAAC,CACV,eAAM,EAAE,EAAE,KAAK,iCAAwB,IAAI,EAAC,OAAO,YAChD,KAAK,GACD,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
2
|
+
/** Visible field label, rendered in a `<label>` linked to the textarea. */
|
|
3
|
+
label?: React.ReactNode;
|
|
4
|
+
/** Helper text under the label, linked via `aria-describedby`. */
|
|
5
|
+
description?: React.ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* Error message. When set, the control gets `aria-invalid="true"`, the
|
|
8
|
+
* message is announced (`role="alert"`) and linked via `aria-describedby`.
|
|
9
|
+
*/
|
|
10
|
+
error?: React.ReactNode;
|
|
11
|
+
/** Mark required: shows an asterisk and sets the native `required`. */
|
|
12
|
+
required?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Initial visible rows. Alias of the native `rows`; `minRows` wins if both
|
|
15
|
+
* are passed (kept for parity with Mantine's `minRows`). This is a static
|
|
16
|
+
* minimum — v0 does not auto-grow the textarea.
|
|
17
|
+
*/
|
|
18
|
+
minRows?: number;
|
|
19
|
+
/** Class on the wrapping element. */
|
|
20
|
+
className?: string;
|
|
21
|
+
/** Class applied to the native `<textarea>`. */
|
|
22
|
+
textareaClassName?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Labeled multi-line text input. Wraps a native `<textarea>` (ref-forwarded),
|
|
26
|
+
* same label/description/error wiring as `<TextInput>`. Auto-themed.
|
|
27
|
+
*
|
|
28
|
+
* `minRows` is a static minimum-rows hint (maps to the native `rows`); v0 does
|
|
29
|
+
* not auto-grow — note this limitation in the README.
|
|
30
|
+
*/
|
|
31
|
+
export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaProps & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
32
|
+
//# sourceMappingURL=Textarea.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../src/ui/Textarea.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,aACf,SAAQ,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC;IACzD,2EAA2E;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,kEAAkE;IAClE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,+GAsEpB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useId } from 'react';
|
|
3
|
+
import { useBlocksStyles } from './styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* Labeled multi-line text input. Wraps a native `<textarea>` (ref-forwarded),
|
|
6
|
+
* same label/description/error wiring as `<TextInput>`. Auto-themed.
|
|
7
|
+
*
|
|
8
|
+
* `minRows` is a static minimum-rows hint (maps to the native `rows`); v0 does
|
|
9
|
+
* not auto-grow — note this limitation in the README.
|
|
10
|
+
*/
|
|
11
|
+
export const Textarea = forwardRef(function Textarea({ label, description, error, required, minRows, rows, className, textareaClassName, id, style, ...rest }, ref) {
|
|
12
|
+
useBlocksStyles();
|
|
13
|
+
const reactId = useId();
|
|
14
|
+
const inputId = id ?? `ci-textarea-${reactId}`;
|
|
15
|
+
const descId = `${inputId}-desc`;
|
|
16
|
+
const errId = `${inputId}-err`;
|
|
17
|
+
const hasError = error != null && error !== false;
|
|
18
|
+
const describedBy = [description != null ? descId : null, hasError ? errId : null]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(' ') || undefined;
|
|
21
|
+
return (_jsxs("div", { className: className, "data-civitai-ui": "textarea", "data-invalid": hasError ? 'true' : undefined, style: style, children: [label != null ? (_jsxs("label", { htmlFor: inputId, "data-civitai-ui-label": true, children: [label, required ? (_jsx("span", { "data-civitai-ui-required": true, "aria-hidden": "true", children: "*" })) : null] })) : null, description != null ? (_jsx("span", { id: descId, "data-civitai-ui-description": true, children: description })) : null, _jsx("textarea", { ref: ref, ...rest, id: inputId, className: textareaClassName, "data-civitai-ui-control": true, rows: minRows ?? rows ?? 3, required: required, "aria-invalid": hasError || undefined, "aria-describedby": describedBy, "aria-required": required || undefined }), hasError ? (_jsx("span", { id: errId, "data-civitai-ui-error": true, role: "alert", children: error })) : null] }));
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=Textarea.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/ui/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA2B9C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAChC,SAAS,QAAQ,CACf,EACE,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,EAAE,EACF,KAAK,EACL,GAAG,IAAI,EACR,EACD,GAAG;IAEH,eAAe,EAAE,CAAC;IAClB,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,OAAO,GAAG,EAAE,IAAI,eAAe,OAAO,EAAE,CAAC;IAC/C,MAAM,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC;IACjC,MAAM,KAAK,GAAG,GAAG,OAAO,MAAM,CAAC;IAC/B,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,CAAC;IAClD,MAAM,WAAW,GACf,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;SAC3D,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;IAE5B,OAAO,CACL,eACE,SAAS,EAAE,SAAS,qBACJ,UAAU,kBACZ,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAC3C,KAAK,EAAE,KAAK,aAEX,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CACf,iBAAO,OAAO,EAAE,OAAO,4CACpB,KAAK,EACL,QAAQ,CAAC,CAAC,CAAC,CACV,gEAA2C,MAAM,kBAE1C,CACR,CAAC,CAAC,CAAC,IAAI,IACF,CACT,CAAC,CAAC,CAAC,IAAI,EACP,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,CACrB,eAAM,EAAE,EAAE,MAAM,iDACb,WAAW,GACP,CACR,CAAC,CAAC,CAAC,IAAI,EACR,mBACE,GAAG,EAAE,GAAG,KACJ,IAAI,EACR,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,iBAAiB,mCAE5B,IAAI,EAAE,OAAO,IAAI,IAAI,IAAI,CAAC,EAC1B,QAAQ,EAAE,QAAQ,kBACJ,QAAQ,IAAI,SAAS,sBACjB,WAAW,mBACd,QAAQ,IAAI,SAAS,GACpC,EACD,QAAQ,CAAC,CAAC,CAAC,CACV,eAAM,EAAE,EAAE,KAAK,iCAAwB,IAAI,EAAC,OAAO,YAChD,KAAK,GACD,CACR,CAAC,CAAC,CAAC,IAAI,IACJ,CACP,CAAC;AACJ,CAAC,CACF,CAAC"}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@civitai/blocks-react/ui` — opinionated UI components for App Block authoring.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Two surfaces:
|
|
5
|
+
*
|
|
6
|
+
* 1. The headless, manifest-driven `SettingsForm` (W3 — host-themed native
|
|
7
|
+
* controls; its contract is intentionally unstyled).
|
|
8
|
+
* 2. The W6 component pack — a small, Civitai-looking, self-styled component
|
|
9
|
+
* set (Button, TextInput, Textarea, Card, Stack, Group, Alert, Loader,
|
|
10
|
+
* Badge, Modal). Zero setup: rendering any of them runs `useBlocksStyles()`
|
|
11
|
+
* which injects the pack's CSS into the block document's `<head>` once.
|
|
12
|
+
* Theme via your block's `data-theme` root (gotcha #60).
|
|
13
|
+
*
|
|
14
|
+
* Importing from `/ui` (not the package root) keeps a transport-only block's
|
|
15
|
+
* bundle lean.
|
|
8
16
|
*/
|
|
9
17
|
export { SettingsForm, SettingsFormError, isFieldVisible } from './SettingsForm.js';
|
|
10
18
|
export type { SettingsFormProps } from './SettingsForm.js';
|
|
19
|
+
export { injectBlocksStyles, useBlocksStyles, BLOCKS_UI_STYLES, } from './styles.js';
|
|
20
|
+
export { Button } from './Button.js';
|
|
21
|
+
export type { ButtonProps, ButtonVariant, ButtonSize } from './Button.js';
|
|
22
|
+
export { TextInput } from './TextInput.js';
|
|
23
|
+
export type { TextInputProps } from './TextInput.js';
|
|
24
|
+
export { Textarea } from './Textarea.js';
|
|
25
|
+
export type { TextareaProps } from './Textarea.js';
|
|
26
|
+
export { Card } from './Card.js';
|
|
27
|
+
export type { CardProps, CardPadding } from './Card.js';
|
|
28
|
+
export { Stack } from './Stack.js';
|
|
29
|
+
export type { StackProps } from './Stack.js';
|
|
30
|
+
export { Group } from './Group.js';
|
|
31
|
+
export type { GroupProps } from './Group.js';
|
|
32
|
+
export { Alert } from './Alert.js';
|
|
33
|
+
export type { AlertProps, AlertColor } from './Alert.js';
|
|
34
|
+
export { Loader } from './Loader.js';
|
|
35
|
+
export type { LoaderProps, LoaderSize } from './Loader.js';
|
|
36
|
+
export { Badge } from './Badge.js';
|
|
37
|
+
export type { BadgeProps, BadgeVariant, BadgeSize } from './Badge.js';
|
|
38
|
+
export { Modal } from './Modal.js';
|
|
39
|
+
export type { ModalProps, ModalSize } from './Modal.js';
|
|
11
40
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/ui/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/ui/index.js
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `@civitai/blocks-react/ui` — opinionated UI components for App Block authoring.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Two surfaces:
|
|
5
|
+
*
|
|
6
|
+
* 1. The headless, manifest-driven `SettingsForm` (W3 — host-themed native
|
|
7
|
+
* controls; its contract is intentionally unstyled).
|
|
8
|
+
* 2. The W6 component pack — a small, Civitai-looking, self-styled component
|
|
9
|
+
* set (Button, TextInput, Textarea, Card, Stack, Group, Alert, Loader,
|
|
10
|
+
* Badge, Modal). Zero setup: rendering any of them runs `useBlocksStyles()`
|
|
11
|
+
* which injects the pack's CSS into the block document's `<head>` once.
|
|
12
|
+
* Theme via your block's `data-theme` root (gotcha #60).
|
|
13
|
+
*
|
|
14
|
+
* Importing from `/ui` (not the package root) keeps a transport-only block's
|
|
15
|
+
* bundle lean.
|
|
8
16
|
*/
|
|
17
|
+
// W3 — manifest-driven settings form (host-themed native controls).
|
|
9
18
|
export { SettingsForm, SettingsFormError, isFieldVisible } from './SettingsForm.js';
|
|
19
|
+
// W6 — runtime style injection.
|
|
20
|
+
export { injectBlocksStyles, useBlocksStyles, BLOCKS_UI_STYLES, } from './styles.js';
|
|
21
|
+
// W6 — component pack.
|
|
22
|
+
export { Button } from './Button.js';
|
|
23
|
+
export { TextInput } from './TextInput.js';
|
|
24
|
+
export { Textarea } from './Textarea.js';
|
|
25
|
+
export { Card } from './Card.js';
|
|
26
|
+
export { Stack } from './Stack.js';
|
|
27
|
+
export { Group } from './Group.js';
|
|
28
|
+
export { Alert } from './Alert.js';
|
|
29
|
+
export { Loader } from './Loader.js';
|
|
30
|
+
export { Badge } from './Badge.js';
|
|
31
|
+
export { Modal } from './Modal.js';
|
|
10
32
|
//# sourceMappingURL=index.js.map
|
package/dist/ui/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGpF,gCAAgC;AAChC,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,uBAAuB;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** The full stylesheet shipped by the pack. Exported for SSR/manual use. */
|
|
2
|
+
export declare const BLOCKS_UI_STYLES = "\n:root {\n --ci-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --ci-radius: 8px;\n --ci-color-text: #1a1a1a;\n --ci-color-text-dimmed: #6b7280;\n --ci-color-surface: #ffffff;\n --ci-color-surface-2: #f4f4f5;\n --ci-color-border: #e0e0e3;\n --ci-color-primary: #228be6;\n --ci-color-primary-hover: #1c7ed6;\n --ci-color-primary-fg: #ffffff;\n --ci-color-error: #e03131;\n --ci-color-success: #2f9e44;\n --ci-color-warning: #f08c00;\n --ci-color-info: #1971c2;\n}\n\n[data-theme='light'] {\n --ci-color-text: #1a1a1a;\n --ci-color-text-dimmed: #6b7280;\n --ci-color-surface: #ffffff;\n --ci-color-surface-2: #f4f4f5;\n --ci-color-border: #e0e0e3;\n}\n\n[data-theme='dark'] {\n --ci-color-text: #e6e6e6;\n --ci-color-text-dimmed: #909296;\n --ci-color-surface: #1a1b1e;\n --ci-color-surface-2: #25262b;\n --ci-color-border: #2c2e33;\n --ci-color-primary: #228be6;\n --ci-color-primary-hover: #339af0;\n --ci-color-primary-fg: #ffffff;\n --ci-color-error: #ff6b6b;\n --ci-color-success: #51cf66;\n --ci-color-warning: #ffa94d;\n --ci-color-info: #4dabf7;\n}\n\n\n[data-civitai-ui] {\n box-sizing: border-box;\n font-family: var(--ci-font);\n}\n[data-civitai-ui] *,\n[data-civitai-ui] *::before,\n[data-civitai-ui] *::after {\n box-sizing: border-box;\n}\n\n/* ----- Button ----- */\n[data-civitai-ui='button'] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: 1px solid transparent;\n border-radius: var(--ci-radius);\n font-family: var(--ci-font);\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n user-select: none;\n text-decoration: none;\n transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;\n background: var(--ci-color-primary);\n color: var(--ci-color-primary-fg);\n}\n[data-civitai-ui='button'][data-size='sm'] { height: 30px; padding: 0 14px; font-size: 13px; }\n[data-civitai-ui='button'][data-size='md'] { height: 36px; padding: 0 18px; font-size: 14px; }\n[data-civitai-ui='button'][data-size='lg'] { height: 44px; padding: 0 22px; font-size: 16px; }\n[data-civitai-ui='button'][data-full-width='true'] { width: 100%; }\n[data-civitai-ui='button'][data-variant='filled'] {\n background: var(--ci-color-primary);\n color: var(--ci-color-primary-fg);\n border-color: var(--ci-color-primary);\n}\n[data-civitai-ui='button'][data-variant='filled']:hover:not(:disabled) {\n background: var(--ci-color-primary-hover);\n border-color: var(--ci-color-primary-hover);\n}\n[data-civitai-ui='button'][data-variant='light'] {\n background: color-mix(in srgb, var(--ci-color-primary) 12%, transparent);\n color: var(--ci-color-primary);\n border-color: transparent;\n}\n[data-civitai-ui='button'][data-variant='light']:hover:not(:disabled) {\n background: color-mix(in srgb, var(--ci-color-primary) 22%, transparent);\n}\n[data-civitai-ui='button'][data-variant='outline'] {\n background: transparent;\n color: var(--ci-color-primary);\n border-color: var(--ci-color-primary);\n}\n[data-civitai-ui='button'][data-variant='outline']:hover:not(:disabled) {\n background: color-mix(in srgb, var(--ci-color-primary) 10%, transparent);\n}\n[data-civitai-ui='button'][data-variant='subtle'] {\n background: transparent;\n color: var(--ci-color-primary);\n border-color: transparent;\n}\n[data-civitai-ui='button'][data-variant='subtle']:hover:not(:disabled) {\n background: color-mix(in srgb, var(--ci-color-primary) 10%, transparent);\n}\n[data-civitai-ui='button']:disabled,\n[data-civitai-ui='button'][aria-busy='true'] {\n opacity: 0.6;\n cursor: not-allowed;\n}\n[data-civitai-ui='button'] [data-civitai-ui-section] {\n display: inline-flex;\n align-items: center;\n}\n\n/* ----- TextInput / Textarea ----- */\n[data-civitai-ui='text-input'],\n[data-civitai-ui='textarea'] {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n[data-civitai-ui-label] {\n font-size: 14px;\n font-weight: 600;\n color: var(--ci-color-text);\n}\n[data-civitai-ui-required] {\n color: var(--ci-color-error);\n margin-left: 2px;\n}\n[data-civitai-ui-description] {\n font-size: 12px;\n color: var(--ci-color-text-dimmed);\n}\n[data-civitai-ui-error] {\n font-size: 12px;\n color: var(--ci-color-error);\n}\n[data-civitai-ui-control] {\n width: 100%;\n font-family: var(--ci-font);\n font-size: 14px;\n color: var(--ci-color-text);\n background: var(--ci-color-surface);\n border: 1px solid var(--ci-color-border);\n border-radius: var(--ci-radius);\n padding: 8px 12px;\n transition: border-color 120ms ease;\n}\n[data-civitai-ui-control]:focus {\n outline: none;\n border-color: var(--ci-color-primary);\n}\n[data-civitai-ui-control][aria-invalid='true'] {\n border-color: var(--ci-color-error);\n}\n[data-civitai-ui-control]:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\ntextarea[data-civitai-ui-control] {\n resize: vertical;\n line-height: 1.5;\n}\n\n/* ----- Card ----- */\n[data-civitai-ui='card'] {\n background: var(--ci-color-surface);\n border-radius: var(--ci-radius);\n color: var(--ci-color-text);\n}\n[data-civitai-ui='card'][data-with-border='true'] {\n border: 1px solid var(--ci-color-border);\n}\n[data-civitai-ui='card'][data-padding='sm'] { padding: 10px; }\n[data-civitai-ui='card'][data-padding='md'] { padding: 16px; }\n[data-civitai-ui='card'][data-padding='lg'] { padding: 24px; }\n\n/* ----- Stack / Group ----- */\n[data-civitai-ui='stack'] {\n display: flex;\n flex-direction: column;\n}\n[data-civitai-ui='group'] {\n display: flex;\n flex-direction: row;\n}\n\n/* ----- Alert ----- */\n[data-civitai-ui='alert'] {\n display: flex;\n gap: 10px;\n align-items: flex-start;\n padding: 12px 14px;\n border-radius: var(--ci-radius);\n border: 1px solid transparent;\n font-size: 14px;\n color: var(--ci-color-text);\n}\n[data-civitai-ui='alert'][data-color='info'] {\n background: color-mix(in srgb, var(--ci-color-info) 12%, transparent);\n border-color: color-mix(in srgb, var(--ci-color-info) 35%, transparent);\n}\n[data-civitai-ui='alert'][data-color='success'] {\n background: color-mix(in srgb, var(--ci-color-success) 12%, transparent);\n border-color: color-mix(in srgb, var(--ci-color-success) 35%, transparent);\n}\n[data-civitai-ui='alert'][data-color='warning'] {\n background: color-mix(in srgb, var(--ci-color-warning) 14%, transparent);\n border-color: color-mix(in srgb, var(--ci-color-warning) 35%, transparent);\n}\n[data-civitai-ui='alert'][data-color='error'] {\n background: color-mix(in srgb, var(--ci-color-error) 12%, transparent);\n border-color: color-mix(in srgb, var(--ci-color-error) 35%, transparent);\n}\n[data-civitai-ui='alert'] [data-civitai-ui-alert-body] {\n flex: 1;\n min-width: 0;\n}\n[data-civitai-ui='alert'] [data-civitai-ui-alert-title] {\n font-weight: 600;\n margin-bottom: 2px;\n}\n[data-civitai-ui='alert'] [data-civitai-ui-alert-close] {\n background: transparent;\n border: none;\n cursor: pointer;\n color: inherit;\n font-size: 16px;\n line-height: 1;\n padding: 0;\n opacity: 0.7;\n}\n[data-civitai-ui='alert'] [data-civitai-ui-alert-close]:hover {\n opacity: 1;\n}\n\n/* ----- Loader ----- */\n[data-civitai-ui='loader'] {\n display: inline-block;\n border-radius: 50%;\n border-style: solid;\n border-color: color-mix(in srgb, currentColor 25%, transparent);\n border-top-color: currentColor;\n color: var(--ci-color-primary);\n animation: civitai-ui-spin 0.7s linear infinite;\n}\n[data-civitai-ui='loader'][data-size='sm'] { width: 16px; height: 16px; border-width: 2px; }\n[data-civitai-ui='loader'][data-size='md'] { width: 22px; height: 22px; border-width: 3px; }\n[data-civitai-ui='loader'][data-size='lg'] { width: 32px; height: 32px; border-width: 4px; }\n@keyframes civitai-ui-spin {\n to { transform: rotate(360deg); }\n}\n[data-civitai-ui='button'] [data-civitai-ui='loader'] {\n color: currentColor;\n}\n\n/* ----- Badge ----- */\n[data-civitai-ui='badge'] {\n display: inline-flex;\n align-items: center;\n border: 1px solid transparent;\n border-radius: 999px;\n font-weight: 600;\n line-height: 1;\n white-space: nowrap;\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n[data-civitai-ui='badge'][data-size='sm'] { height: 18px; padding: 0 8px; font-size: 10px; }\n[data-civitai-ui='badge'][data-size='md'] { height: 22px; padding: 0 10px; font-size: 11px; }\n[data-civitai-ui='badge'][data-size='lg'] { height: 26px; padding: 0 12px; font-size: 13px; }\n[data-civitai-ui='badge'][data-variant='filled'] {\n background: var(--ci-color-primary);\n color: var(--ci-color-primary-fg);\n border-color: var(--ci-color-primary);\n}\n[data-civitai-ui='badge'][data-variant='light'] {\n background: color-mix(in srgb, var(--ci-color-primary) 14%, transparent);\n color: var(--ci-color-primary);\n}\n[data-civitai-ui='badge'][data-variant='outline'] {\n background: transparent;\n color: var(--ci-color-primary);\n border-color: var(--ci-color-primary);\n}\n\n/* ----- Modal ----- */\n[data-civitai-ui='modal-overlay'] {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.55);\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: 32px 16px;\n overflow-y: auto;\n z-index: 1000;\n}\n[data-civitai-ui='modal'] {\n background: var(--ci-color-surface);\n color: var(--ci-color-text);\n border: 1px solid var(--ci-color-border);\n border-radius: var(--ci-radius);\n box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);\n width: 100%;\n max-width: 440px;\n outline: none;\n}\n[data-civitai-ui='modal'][data-size='sm'] { max-width: 340px; }\n[data-civitai-ui='modal'][data-size='md'] { max-width: 440px; }\n[data-civitai-ui='modal'][data-size='lg'] { max-width: 620px; }\n[data-civitai-ui='modal'] [data-civitai-ui-modal-header] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 16px 18px;\n border-bottom: 1px solid var(--ci-color-border);\n}\n[data-civitai-ui='modal'] [data-civitai-ui-modal-title] {\n font-size: 16px;\n font-weight: 700;\n margin: 0;\n}\n[data-civitai-ui='modal'] [data-civitai-ui-modal-close] {\n background: transparent;\n border: none;\n cursor: pointer;\n color: var(--ci-color-text-dimmed);\n font-size: 20px;\n line-height: 1;\n padding: 0;\n}\n[data-civitai-ui='modal'] [data-civitai-ui-modal-close]:hover {\n color: var(--ci-color-text);\n}\n[data-civitai-ui='modal'] [data-civitai-ui-modal-body] {\n padding: 18px;\n}\n";
|
|
3
|
+
/**
|
|
4
|
+
* Inject the pack's stylesheet into a document's `<head>` exactly once.
|
|
5
|
+
* Idempotent: subsequent calls (including from other components) detect the
|
|
6
|
+
* marker `<style>` and no-op. Safe to call from any component's effect.
|
|
7
|
+
*
|
|
8
|
+
* @param doc Target document. Defaults to the ambient `document`. No-op when
|
|
9
|
+
* no document is available (e.g. SSR) — callers in the browser get styling,
|
|
10
|
+
* server renders fall back to the unstyled-but-functional markup.
|
|
11
|
+
*/
|
|
12
|
+
export declare function injectBlocksStyles(doc?: Document): void;
|
|
13
|
+
/**
|
|
14
|
+
* Hook that injects the pack's styles once on mount. Every `/ui` component
|
|
15
|
+
* calls this so rendering any of them is enough to get the styling — the
|
|
16
|
+
* author never imports CSS or runs a setup step.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useBlocksStyles(): void;
|
|
19
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/ui/styles.ts"],"names":[],"mappings":"AA4XA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,uzUAAgC,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,CAAC,EAAE,QAAQ,GAAG,IAAI,CAgBvD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAItC"}
|