@civitai/blocks-react 0.45.0 → 0.46.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.
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The post-write abuse seam for a shared board: a two-step control that files a
3
+ * row for PLATFORM moderator review via `useSharedStorage().report()`.
4
+ *
5
+ * 🔴 REPORTING IS ESCALATION, NOT REMOVAL, and this component exists so that
6
+ * fact is stated identically in every block. `report()` files the row and its
7
+ * own contract says filing does NOT hide it — a moderator decides. An app owner
8
+ * has no server-side hide to offer instead either: `update` and `withdraw` are
9
+ * author-scoped, so they reject for anyone but the row's author.
10
+ *
11
+ * 🔴 THE VISIBLE COPY IS NOT OVERRIDABLE — and that guarantee is exactly one
12
+ * thing, so do not read it as more. What is fixed is the WORDING THIS COMPONENT
13
+ * RENDERS: the confirm question, the failure line and the settled line are each
14
+ * pinned whole by tests, so none of them can come to imply a deletion. It does
15
+ * NOT constrain what {@link ReportButtonProps.onReport} actually does — a
16
+ * consumer can wire a real delete behind it and this control will still settle
17
+ * to "Reported for review" — and it cannot stop a host page restyling the
18
+ * settled text out of view. The honest claim is that the wording cannot drift by
19
+ * accident across blocks, which is what three divergent hand-rolled copies had
20
+ * already produced.
21
+ *
22
+ * The caller decides WHO sees it. Render it only for a viewer who is signed in
23
+ * and does not own the row: `report` rejects for an anonymous viewer, and an
24
+ * author has a real Remove. Offering it otherwise is offering an error.
25
+ *
26
+ * @example
27
+ * // 🔴 Key it by the ROW, not by index — the settled state belongs to the row,
28
+ * // and a list that re-orders under an index key shows a settled report
29
+ * // against a row nobody reported.
30
+ * {!isOwn && viewerId != null && (
31
+ * <ReportButton
32
+ * key={item.key}
33
+ * noun="generator"
34
+ * reported={myReports.has(item.key)}
35
+ * onReport={() => shared.report(item.key)}
36
+ * data-testid={`gen-${item.key}-report`}
37
+ * />
38
+ * )}
39
+ */
40
+ export interface ReportButtonProps {
41
+ /**
42
+ * What the row is, lower-case and singular — "combination", "prompt",
43
+ * "generator", "request". Appears in the confirm question and in both
44
+ * accessible names.
45
+ *
46
+ * 🔴 It is spliced into an `aria-label`, so it is NOT a place for arbitrary
47
+ * text: a sentence here becomes the control's accessible name and can say
48
+ * whatever it likes to exactly the users the fixed wording exists to protect.
49
+ * Pass a bare noun.
50
+ */
51
+ noun: string;
52
+ /**
53
+ * Files the report. Fires ONLY after the viewer confirms. Reject to surface
54
+ * the failure — a rejected report keeps the control armed rather than
55
+ * settling, because one that closed quietly would read as filed.
56
+ */
57
+ onReport: () => Promise<void>;
58
+ /**
59
+ * This viewer has ALREADY reported this row. Renders the settled state
60
+ * directly and skips the handshake.
61
+ *
62
+ * 🔴 THE SHARED STORE CANNOT TELL YOU THIS. `SharedListItem` carries
63
+ * `viewerVoted` and has no report equivalent, so unlike a vote there is no
64
+ * server field to read — the only source is your own app's per-viewer
65
+ * storage, recorded when `onReport` resolves. Supply it if you keep that
66
+ * record: without it the settled state is local-only, so any remount (a
67
+ * `list()` refresh, a tab switch, virtualized scroll) resets the control to
68
+ * "Report" and the same viewer can file the same row again. `report()` is NOT
69
+ * documented idempotent the way `vote` is, so that is a duplicate report
70
+ * rather than a no-op.
71
+ *
72
+ * Flipping this to `true` settles the control silently — no focus move — which
73
+ * is correct for the load-time case it is meant for; stealing focus on mount
74
+ * would be wrong.
75
+ */
76
+ reported?: boolean;
77
+ /**
78
+ * Test hook for the TRIGGER. The other four hooks are DERIVED from it by
79
+ * suffix, so two rows in one list stay distinguishable once armed or settled:
80
+ * `<id>-confirm`, `<id>-cancel`, `<id>-done`, `<id>-prompt`.
81
+ *
82
+ * 🔴 Grep for the SUFFIX, never for the composed value: a composed testid
83
+ * appears nowhere in source as a literal, so a search for `foo-confirm`
84
+ * returns zero whether the selector works or has just been deleted.
85
+ *
86
+ * Omitted, the ids are `report-button`, `report-confirm`, `report-cancel`,
87
+ * `report-done`, `report-confirm-prompt`.
88
+ */
89
+ 'data-testid'?: string;
90
+ }
91
+ export declare function ReportButton({ noun, onReport, reported, 'data-testid': testId, }: ReportButtonProps): React.JSX.Element;
92
+ //# sourceMappingURL=ReportButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportButton.d.ts","sourceRoot":"","sources":["../../src/ui/ReportButton.tsx"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAQ,EACR,QAAgB,EAChB,aAAa,EAAE,MAAM,GACtB,EAAE,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA8MvC"}
@@ -0,0 +1,172 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { Button } from './Button.js';
4
+ import { Group } from './Group.js';
5
+ import { useBlocksStyles } from './styles.js';
6
+ /** Shared by the two text renders so they cannot drift apart. */
7
+ const NOTE_STYLE = {
8
+ whiteSpace: 'nowrap',
9
+ fontSize: 12,
10
+ lineHeight: 1.45,
11
+ color: 'var(--civitai-color-text-dimmed)',
12
+ };
13
+ export function ReportButton({ noun, onReport, reported = false, 'data-testid': testId, }) {
14
+ const [confirming, setConfirming] = useState(false);
15
+ const [busy, setBusy] = useState(false);
16
+ const [done, setDone] = useState(false);
17
+ const [failed, setFailed] = useState(false);
18
+ const confirmRef = useRef(null);
19
+ const cancelRef = useRef(null);
20
+ const doneRef = useRef(null);
21
+ /**
22
+ * Monotonic id of the CURRENT attempt. Every settle compares against it and
23
+ * no-ops if it has moved on.
24
+ *
25
+ * 🔴 A single "abandoned" BOOLEAN is not enough, and the difference is not
26
+ * theoretical — it was measured. A boolean reset at the top of each attempt
27
+ * protects exactly one abandoned request and only until the next confirm, so
28
+ * cancel → re-arm → confirm let the FIRST request settle the control
29
+ * ("Reported for review" for a report the viewer withdrew from, while a second
30
+ * was still in flight) and, on the rejecting path, clear the shared `busy` so
31
+ * Confirm re-enabled mid-flight — three `onReport` calls for one row, against
32
+ * a `report()` that is not idempotent. An id per attempt cannot do that:
33
+ * anything that ends an attempt bumps it, and a superseded settle is inert.
34
+ */
35
+ const attemptRef = useRef(0);
36
+ const settled = done || reported;
37
+ useBlocksStyles();
38
+ const ids = testId
39
+ ? {
40
+ trigger: testId,
41
+ confirm: `${testId}-confirm`,
42
+ cancel: `${testId}-cancel`,
43
+ done: `${testId}-done`,
44
+ prompt: `${testId}-prompt`,
45
+ }
46
+ : {
47
+ trigger: 'report-button',
48
+ confirm: 'report-confirm',
49
+ cancel: 'report-cancel',
50
+ done: 'report-done',
51
+ prompt: 'report-confirm-prompt',
52
+ };
53
+ // 🔴 Move focus with the control, at BOTH transitions. Each step replaces the
54
+ // element the viewer just activated, so without this a keyboard user is
55
+ // dropped to <body> and must Tab from the top of the document to reach the
56
+ // second half of a two-step confirm.
57
+ //
58
+ // Focusing the settled note also does the announcing that `role="status"`
59
+ // alone cannot be relied on for here: that region is INSERTED already
60
+ // carrying its text, and a live region generally has to exist before its
61
+ // content changes to be announced. Moving focus to it is what makes the
62
+ // outcome reach a screen-reader user rather than hoping.
63
+ //
64
+ // 🔴 Keyed on `confirming` ALONE, deliberately. Keying it on `busy` too meant
65
+ // the effect re-fired when a request finished, so a viewer who pressed Confirm
66
+ // and then moved focus elsewhere had it YANKED BACK on rejection. `busy` is a
67
+ // request-lifecycle flag, not a "the control moved" transition.
68
+ useEffect(() => {
69
+ if (confirming)
70
+ confirmRef.current?.focus();
71
+ }, [confirming]);
72
+ useEffect(() => {
73
+ if (done)
74
+ doneRef.current?.focus();
75
+ }, [done]);
76
+ // 🔴 Confirm carries `loading`, which sets the native `disabled`, so the
77
+ // browser BLURS it the moment a request starts. Move focus to Cancel — which
78
+ // stays enabled precisely so the in-flight state has a live control — or the
79
+ // viewer is dropped to <body> with nothing tabbable, which is the failure this
80
+ // component's own focus handling exists to prevent.
81
+ useEffect(() => {
82
+ if (busy)
83
+ cancelRef.current?.focus();
84
+ }, [busy]);
85
+ // 🔴 Server truth ENDS the handshake rather than hiding it. Without this the
86
+ // strip stays mounted underneath: a later `reported: false` resurrected a
87
+ // stale "Could not send" against a control the viewer had seen settle, and a
88
+ // rejection arriving after the flip landed behind an unmounted strip — the
89
+ // same dropped-error state the Cancel handling above exists to prevent.
90
+ useEffect(() => {
91
+ if (reported) {
92
+ // 🔴 Bump the attempt too, or an in-flight request keeps writing into a
93
+ // control that has already settled: measured, a rejection arriving after
94
+ // this flip set `failed` behind the settled note, and withdrawing
95
+ // `reported` then surfaced "Could not send — try again?" for a report that
96
+ // was never submitted.
97
+ //
98
+ // 🔴 Neither `setBusy(false)` nor `setFailed(false)` is redundant here, and
99
+ // each went a full round with NO coverage on either tier before a case was
100
+ // written for it — see "a withdrawn `reported` leaves Confirm USABLE" and
101
+ // "does not leave a stale FAILURE behind either". Both now fail on the
102
+ // unit tier if their line is deleted.
103
+ //
104
+ // What they prevent, and note it surfaces on the NEXT ARM, not on the
105
+ // withdraw itself (this effect has already cleared `confirming`, so the
106
+ // viewer lands on the trigger): the attempt is superseded, so its
107
+ // `finally` never clears the shared `busy` and its rejection never clears
108
+ // `failed`. Re-arm and you get Confirm disabled with a spinner, or "Could
109
+ // not send" for a report never submitted in that attempt. Clearing both
110
+ // here is what ends the attempt completely rather than half-way.
111
+ attemptRef.current += 1;
112
+ setConfirming(false);
113
+ setFailed(false);
114
+ setBusy(false);
115
+ }
116
+ }, [reported]);
117
+ if (settled) {
118
+ return (_jsx("span", { ref: doneRef, tabIndex: -1, "data-testid": ids.done, role: "status", style: { ...NOTE_STYLE, outline: 'none' }, children: "Reported for review" }));
119
+ }
120
+ if (!confirming) {
121
+ return (_jsx(Button, { size: "sm", variant: "subtle", onClick: () => setConfirming(true), "data-testid": ids.trigger, "aria-label": `Report this ${noun} to moderators`, children: "Report" }));
122
+ }
123
+ const confirm = async () => {
124
+ const attempt = (attemptRef.current += 1);
125
+ /** This attempt is still the one on screen. */
126
+ const current = () => attemptRef.current === attempt;
127
+ setBusy(true);
128
+ setFailed(false);
129
+ try {
130
+ await onReport();
131
+ // 🔴 Superseded — the viewer cancelled, or the parent settled us. (A
132
+ // newer attempt cannot be started without one of those first, since
133
+ // Confirm is natively disabled while busy; the check is depth, not a
134
+ // reachable third case.) Settling here would report an action this viewer
135
+ // withdrew from.
136
+ if (!current())
137
+ return;
138
+ setDone(true);
139
+ setConfirming(false);
140
+ }
141
+ catch {
142
+ // Same on the failure side: a rejection belonging to an abandoned or
143
+ // superseded attempt must not resurrect a strip, nor mark a live attempt
144
+ // failed.
145
+ if (!current())
146
+ return;
147
+ setFailed(true);
148
+ }
149
+ finally {
150
+ // 🔴 Load-bearing, not defensive. A superseded attempt clearing the shared
151
+ // `busy` is what re-enabled Confirm while a newer request was still
152
+ // running, which is how one row got filed three times.
153
+ if (current())
154
+ setBusy(false);
155
+ }
156
+ };
157
+ return (_jsxs(Group, { gap: 6, align: "center", wrap: false, "data-testid": ids.prompt, children: [_jsx("span", { style: NOTE_STYLE, ...(failed ? { role: 'alert' } : {}), children: failed ? 'Could not send — try again?' : `Send this ${noun} to moderators for review?` }), _jsx(Button, { ref: confirmRef, size: "sm", loading: busy, onClick: confirm, "data-testid": ids.confirm, "aria-label": `Confirm reporting this ${noun} to moderators`, children: "Report" }), _jsx(Button, { ref: cancelRef, size: "sm", variant: "subtle",
158
+ // 🔴 DELIBERATELY NOT disabled in flight. It was, briefly, to stop a late
159
+ // resolve settling a cancelled report — but `onReport` here is
160
+ // `shared.report()` over a postMessage bridge with no timeout, so a
161
+ // reply that never arrives left BOTH buttons disabled and the control
162
+ // wedged with no way back short of a remount. Trading a rare race for a
163
+ // permanent dead end is the wrong side of that trade; the attempt token
164
+ // closes the race without taking the escape hatch away.
165
+ onClick: () => {
166
+ attemptRef.current += 1;
167
+ setBusy(false);
168
+ setFailed(false);
169
+ setConfirming(false);
170
+ }, "data-testid": ids.cancel, "aria-label": "Cancel the report", children: "Cancel" })] }));
171
+ }
172
+ //# sourceMappingURL=ReportButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReportButton.js","sourceRoot":"","sources":["../../src/ui/ReportButton.tsx"],"names":[],"mappings":"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"}
@@ -38,6 +38,8 @@ export { Loader } from './Loader.js';
38
38
  export type { LoaderProps, LoaderSize } from './Loader.js';
39
39
  export { Badge } from './Badge.js';
40
40
  export type { BadgeProps, BadgeVariant, BadgeSize } from './Badge.js';
41
+ export { ReportButton } from './ReportButton.js';
42
+ export type { ReportButtonProps } from './ReportButton.js';
41
43
  export { Modal } from './Modal.js';
42
44
  export type { ModalProps, ModalSize } from './Modal.js';
43
45
  export { Slider } from './Slider.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAK3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,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;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAK3D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9E,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,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC"}
package/dist/ui/index.js CHANGED
@@ -33,6 +33,7 @@ export { Group } from './Group.js';
33
33
  export { Alert } from './Alert.js';
34
34
  export { Loader } from './Loader.js';
35
35
  export { Badge } from './Badge.js';
36
+ export { ReportButton } from './ReportButton.js';
36
37
  export { Modal } from './Modal.js';
37
38
  export { Slider } from './Slider.js';
38
39
  export { NumberInput } from './NumberInput.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGpF,4EAA4E;AAC5E,6EAA6E;AAC7E,mEAAmE;AACnE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG/D,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;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGpF,4EAA4E;AAC5E,6EAA6E;AAC7E,mEAAmE;AACnE,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAG/D,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,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@civitai/blocks-react",
3
- "version": "0.45.0",
3
+ "version": "0.46.0",
4
4
  "description": "React hooks and iframe transport for Civitai Apps. Pairs with @civitai/app-sdk/blocks.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,8 +31,8 @@
31
31
  "node": ">=20"
32
32
  },
33
33
  "dependencies": {
34
- "@civitai/theme": "0.3.0",
35
- "@civitai/components": "0.4.0"
34
+ "@civitai/theme": "0.3.1",
35
+ "@civitai/components": "0.4.1"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@civitai/app-sdk": ">=0.29.0 <1.0.0",