@epoch32/visage 0.0.0-stage → 0.0.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.
Files changed (138) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +110 -2
  3. package/dist/bundle.dev.js +4875 -0
  4. package/dist/index.js +9633 -0
  5. package/dist/src/api/index.js +4002 -0
  6. package/dist/src/charts/index.js +2717 -0
  7. package/dist/src/devtools/index.js +4677 -0
  8. package/dist/src/dom/index.js +1550 -0
  9. package/dist/src/form/index.js +1415 -0
  10. package/dist/src/index.js +11826 -0
  11. package/dist/src/jsx-runtime/index.js +1630 -0
  12. package/dist/src/query/index.js +2422 -0
  13. package/dist/src/router/index.js +1856 -0
  14. package/dist/src/rpc/index.js +3484 -0
  15. package/dist/src/server/index.js +1173 -0
  16. package/dist/src/signals/index.js +1077 -0
  17. package/dist/src/style/index.js +2340 -0
  18. package/dist/src/template/index.js +1149 -0
  19. package/dist/src/ui/index.js +4155 -0
  20. package/dist/src/virtual/index.js +1955 -0
  21. package/dist/src/vite/index.js +984 -0
  22. package/dist/vite/index.js +707 -0
  23. package/package.json +140 -4
  24. package/src/api/client.ts +371 -0
  25. package/src/api/file-router.ts +183 -0
  26. package/src/api/handler.ts +326 -0
  27. package/src/api/index.ts +71 -0
  28. package/src/api/middleware.ts +54 -0
  29. package/src/api/pragma.ts +155 -0
  30. package/src/api/procedure.ts +172 -0
  31. package/src/api/types.ts +249 -0
  32. package/src/charts/Area.tsx +111 -0
  33. package/src/charts/Axis.tsx +126 -0
  34. package/src/charts/Bar.tsx +86 -0
  35. package/src/charts/CartesianGrid.tsx +72 -0
  36. package/src/charts/Chart.tsx +269 -0
  37. package/src/charts/Cursor.tsx +42 -0
  38. package/src/charts/Legend.tsx +56 -0
  39. package/src/charts/Line.tsx +106 -0
  40. package/src/charts/Pie.tsx +88 -0
  41. package/src/charts/Tooltip.tsx +127 -0
  42. package/src/charts/context.ts +30 -0
  43. package/src/charts/index.ts +14 -0
  44. package/src/charts/path.ts +155 -0
  45. package/src/charts/scale.ts +133 -0
  46. package/src/charts/types.ts +50 -0
  47. package/src/devtools/DomTab.tsx +134 -0
  48. package/src/devtools/GraphInspector.tsx +196 -0
  49. package/src/devtools/GraphTab.tsx +315 -0
  50. package/src/devtools/QueryTab.tsx +200 -0
  51. package/src/devtools/RpcTab.tsx +190 -0
  52. package/src/devtools/SignalsTab.tsx +129 -0
  53. package/src/devtools/component.tsx +243 -0
  54. package/src/devtools/highlighter.ts +134 -0
  55. package/src/devtools/hub.ts +175 -0
  56. package/src/devtools/index.ts +20 -0
  57. package/src/devtools/styles.ts +313 -0
  58. package/src/devtools/types.ts +45 -0
  59. package/src/dom/async.ts +232 -0
  60. package/src/dom/control-flow.ts +353 -0
  61. package/src/dom/index.ts +32 -0
  62. package/src/dom/lazy.ts +82 -0
  63. package/src/dom/render.ts +286 -0
  64. package/src/dom/resource.ts +120 -0
  65. package/src/form/form.ts +218 -0
  66. package/src/form/index.ts +17 -0
  67. package/src/form/schema.ts +299 -0
  68. package/src/index.ts +413 -0
  69. package/src/jsx-dev-runtime/index.ts +1 -0
  70. package/src/jsx-runtime/index.ts +112 -0
  71. package/src/jsx-runtime/jsx.d.ts +278 -0
  72. package/src/query/create-mutation.ts +64 -0
  73. package/src/query/create-query.ts +426 -0
  74. package/src/query/focus-manager.ts +68 -0
  75. package/src/query/index.ts +63 -0
  76. package/src/query/mutation-cache.ts +138 -0
  77. package/src/query/online-manager.ts +67 -0
  78. package/src/query/query-cache.ts +369 -0
  79. package/src/query/query-client.ts +248 -0
  80. package/src/query/types.ts +221 -0
  81. package/src/query/utils.ts +132 -0
  82. package/src/router/index.ts +19 -0
  83. package/src/router/router.tsx +352 -0
  84. package/src/rpc/client.ts +317 -0
  85. package/src/rpc/error.ts +70 -0
  86. package/src/rpc/index.ts +52 -0
  87. package/src/rpc/procedure.ts +88 -0
  88. package/src/rpc/router.ts +105 -0
  89. package/src/rpc/server.ts +511 -0
  90. package/src/rpc/types.ts +328 -0
  91. package/src/server/hydrate.ts +21 -0
  92. package/src/server/index.ts +10 -0
  93. package/src/server/render-to-stream.ts +31 -0
  94. package/src/server/render-to-string.ts +125 -0
  95. package/src/signals/computed.ts +217 -0
  96. package/src/signals/context.ts +89 -0
  97. package/src/signals/effect.ts +161 -0
  98. package/src/signals/index.ts +57 -0
  99. package/src/signals/scope.ts +132 -0
  100. package/src/signals/signal.ts +203 -0
  101. package/src/signals/store.ts +163 -0
  102. package/src/signals/system.ts +124 -0
  103. package/src/signals/types.ts +64 -0
  104. package/src/style/component.tsx +122 -0
  105. package/src/style/create-style.ts +229 -0
  106. package/src/style/cx.ts +75 -0
  107. package/src/style/hash.ts +19 -0
  108. package/src/style/index.ts +8 -0
  109. package/src/style/layout.tsx +406 -0
  110. package/src/style/manager.ts +87 -0
  111. package/src/style/parser.ts +257 -0
  112. package/src/style/scale.ts +237 -0
  113. package/src/template/index.ts +4 -0
  114. package/src/template/template.ts +126 -0
  115. package/src/ui/accordion.tsx +286 -0
  116. package/src/ui/command-dialog.tsx +49 -0
  117. package/src/ui/command.tsx +400 -0
  118. package/src/ui/data-table.tsx +322 -0
  119. package/src/ui/dialog.tsx +362 -0
  120. package/src/ui/dropdown-menu.tsx +381 -0
  121. package/src/ui/icon.tsx +69 -0
  122. package/src/ui/index.ts +138 -0
  123. package/src/ui/layout.tsx +13 -0
  124. package/src/ui/popover.tsx +249 -0
  125. package/src/ui/switch.tsx +114 -0
  126. package/src/ui/tabs.tsx +297 -0
  127. package/src/ui/toast.tsx +280 -0
  128. package/src/ui/tooltip.tsx +262 -0
  129. package/src/ui/utils.ts +110 -0
  130. package/src/virtual/index.ts +12 -0
  131. package/src/virtual/virtual-list.tsx +185 -0
  132. package/src/virtual/virtualizer.ts +274 -0
  133. package/src/vite/hmr.ts +38 -0
  134. package/src/vite/index.ts +3 -0
  135. package/src/vite/lucide.ts +124 -0
  136. package/src/vite/plugin.ts +102 -0
  137. package/src/vite/rpc-middleware.ts +82 -0
  138. package/src/vite/types.ts +65 -0
@@ -0,0 +1,112 @@
1
+ import { type Child, insertChild, resolveValue, setAttribute } from "../dom";
2
+ import { formatStyleProp } from "../style/scale";
3
+
4
+ export type { JSX } from "./jsx";
5
+
6
+ const SVG_NS = "http://www.w3.org/2000/svg";
7
+ const SVG_TAGS = new Set([
8
+ "svg",
9
+ "path",
10
+ "circle",
11
+ "rect",
12
+ "g",
13
+ "line",
14
+ "polyline",
15
+ "polygon",
16
+ "text",
17
+ "defs",
18
+ "clipPath",
19
+ "linearGradient",
20
+ "radialGradient",
21
+ "stop"
22
+ ]);
23
+
24
+ export function Fragment(props: { children?: Child }): any {
25
+ if (typeof document === "undefined") {
26
+ return props.children !== undefined ? props.children : [];
27
+ }
28
+ const fragment = document.createDocumentFragment();
29
+ if (props.children !== undefined) {
30
+ insertChild(fragment, props.children);
31
+ }
32
+ return fragment;
33
+ }
34
+
35
+ export function jsx(type: any, props: Record<string, any> = {}, key?: any): any {
36
+ // If it's a Component function
37
+ if (typeof type === "function") {
38
+ return type(props, key);
39
+ }
40
+
41
+ // If it's a DOM element tag
42
+ if (typeof type === "string") {
43
+ const { children, ...restProps } = props;
44
+
45
+ // SSR Server Environment (Node / Bun / Cloudflare Workers without DOM)
46
+ if (typeof document === "undefined") {
47
+ const attributes = new Map<string, any>();
48
+ for (const propName in restProps) {
49
+ const val = restProps[propName];
50
+ if (propName === "className" || propName === "class") {
51
+ const resolved = typeof val === "function" ? val() : val;
52
+ if (resolved) attributes.set("class", resolved);
53
+ } else if (propName === "style") {
54
+ const val = restProps[propName];
55
+ const resolved = resolveValue(val);
56
+ if (typeof resolved === "string") {
57
+ attributes.set("style", resolved);
58
+ } else if (typeof resolved === "object" && resolved !== null) {
59
+ const styleStr = Object.entries(resolved)
60
+ .map(([k, v]) => {
61
+ const finalVal = resolveValue(v);
62
+ const formatted = formatStyleProp(k, finalVal);
63
+ if (!formatted) return "";
64
+ const kebab = k.startsWith("--") ? k : k.replace(/([A-Z])/g, "-$1").toLowerCase();
65
+ return `${kebab}: ${formatted}`;
66
+ })
67
+ .filter(Boolean)
68
+ .join("; ");
69
+ if (styleStr) attributes.set("style", styleStr);
70
+ }
71
+ } else if (!propName.startsWith("on")) {
72
+ const resolved = typeof val === "function" ? val() : val;
73
+ if (resolved === true) {
74
+ attributes.set(propName, propName);
75
+ } else if (resolved !== false && resolved !== null && resolved !== undefined) {
76
+ attributes.set(propName, resolved);
77
+ }
78
+ }
79
+ }
80
+
81
+ const childNodes =
82
+ children !== undefined ? (Array.isArray(children) ? children : [children]) : [];
83
+
84
+ return {
85
+ tagName: type,
86
+ attributes,
87
+ childNodes
88
+ };
89
+ }
90
+
91
+ // Browser / JSDOM Environment
92
+ const isSvg = SVG_TAGS.has(type);
93
+ const element = isSvg ? document.createElementNS(SVG_NS, type) : document.createElement(type);
94
+
95
+ // Apply attributes and event listeners
96
+ for (const propName in restProps) {
97
+ setAttribute(element as HTMLElement, propName, restProps[propName]);
98
+ }
99
+
100
+ // Insert children
101
+ if (children !== undefined) {
102
+ insertChild(element, children);
103
+ }
104
+
105
+ return element;
106
+ }
107
+
108
+ return type;
109
+ }
110
+
111
+ export const jsxs = jsx;
112
+ export const jsxDEV = jsx;
@@ -0,0 +1,278 @@
1
+ import type { Child } from "../dom";
2
+ import type { ReadonlySignal } from "../signals";
3
+
4
+ /**
5
+ * Fine-grained reactive property value.
6
+ *
7
+ * Can be a static value `T`, a reactive `ReadonlySignal<T>`, or a dynamic getter function `() => T`.
8
+ * Visage binds reactive props directly to the DOM attribute or property via fine-grained effects,
9
+ * updating only the exact target attribute when the signal changes without re-rendering the component.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * const count = signal(5);
14
+ *
15
+ * // Direct signal
16
+ * <input disabled={count} />
17
+ *
18
+ * // Getter function
19
+ * <div title={() => `Item count: ${count()}`} />
20
+ * ```
21
+ */
22
+ export type ReactiveProp<T> = T | ReadonlySignal<T> | (() => T);
23
+
24
+ /**
25
+ * Flexible reactive class value supporting strings, conditional objects, arrays, and getters.
26
+ */
27
+ export type ClassValue =
28
+ | string
29
+ | number
30
+ | boolean
31
+ | null
32
+ | undefined
33
+ | (() => any)
34
+ | ClassValue[]
35
+ | Record<string, any>;
36
+
37
+ /**
38
+ * Reactive class / className property.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * // Object conditional syntax
43
+ * <div class={{ active: isActive(), hidden: isHidden() }} />
44
+ *
45
+ * // Array syntax
46
+ * <div class={["btn", isPrimary() ? "btn-primary" : "btn-secondary"]} />
47
+ *
48
+ * // Signal / Getter syntax
49
+ * <div class={() => `theme-${theme()}`} />
50
+ * ```
51
+ */
52
+ export type ClassProp = ReactiveProp<
53
+ string | number | boolean | undefined | null | ClassValue[] | Record<string, any>
54
+ >;
55
+
56
+ /**
57
+ * Standard HTML Element attributes with fine-grained reactive property bindings.
58
+ */
59
+ export type HTMLAttributes<T extends HTMLElement = HTMLElement> = {
60
+ [K in keyof HTMLElementTagNameMap[keyof HTMLElementTagNameMap]]?: any;
61
+ } & {
62
+ class?: ClassProp;
63
+ className?: ClassProp;
64
+ id?: ReactiveProp<string | undefined | null>;
65
+ title?: ReactiveProp<string | undefined | null>;
66
+ tabIndex?: ReactiveProp<number | undefined | null>;
67
+ role?: ReactiveProp<string | undefined | null>;
68
+ hidden?: ReactiveProp<boolean | undefined | null>;
69
+ disabled?: ReactiveProp<boolean | undefined | null>;
70
+ style?: ReactiveProp<
71
+ string | Record<string, ReactiveProp<string | number | undefined | null>> | undefined | null
72
+ >;
73
+ ref?: (el: T) => void;
74
+ dangerouslySetInnerHTML?: { __html: string };
75
+
76
+ // Events
77
+ onClick?: (e: MouseEvent) => void;
78
+ onDblClick?: (e: MouseEvent) => void;
79
+ onMouseDown?: (e: MouseEvent) => void;
80
+ onMouseUp?: (e: MouseEvent) => void;
81
+ onMouseMove?: (e: MouseEvent) => void;
82
+ onMouseEnter?: (e: MouseEvent) => void;
83
+ onMouseLeave?: (e: MouseEvent) => void;
84
+ onKeyDown?: (e: KeyboardEvent) => void;
85
+ onKeyUp?: (e: KeyboardEvent) => void;
86
+ onKeyPress?: (e: KeyboardEvent) => void;
87
+ onInput?: (e: InputEvent & { target: T }) => void;
88
+ onChange?: (e: Event & { target: T }) => void;
89
+ onSubmit?: (e: SubmitEvent) => void;
90
+ onFocus?: (e: FocusEvent) => void;
91
+ onBlur?: (e: FocusEvent) => void;
92
+ onScroll?: (e: Event) => void;
93
+
94
+ children?: Child;
95
+ [attr: string]: any;
96
+ };
97
+
98
+ export type InputAttributes = HTMLAttributes<HTMLInputElement> & {
99
+ type?: ReactiveProp<string>;
100
+ value?: ReactiveProp<string | number | readonly string[] | undefined | null>;
101
+ checked?: ReactiveProp<boolean | undefined | null>;
102
+ placeholder?: ReactiveProp<string | undefined | null>;
103
+ name?: ReactiveProp<string | undefined | null>;
104
+ disabled?: ReactiveProp<boolean | undefined | null>;
105
+ readOnly?: ReactiveProp<boolean | undefined | null>;
106
+ required?: ReactiveProp<boolean | undefined | null>;
107
+ min?: ReactiveProp<string | number | undefined | null>;
108
+ max?: ReactiveProp<string | number | undefined | null>;
109
+ step?: ReactiveProp<string | number | undefined | null>;
110
+ pattern?: ReactiveProp<string | undefined | null>;
111
+ autoFocus?: ReactiveProp<boolean | undefined | null>;
112
+ autoComplete?: ReactiveProp<string | undefined | null>;
113
+ };
114
+
115
+ export type ButtonAttributes = HTMLAttributes<HTMLButtonElement> & {
116
+ type?: ReactiveProp<"button" | "submit" | "reset" | undefined>;
117
+ disabled?: ReactiveProp<boolean | undefined | null>;
118
+ name?: ReactiveProp<string | undefined | null>;
119
+ value?: ReactiveProp<string | number | undefined | null>;
120
+ };
121
+
122
+ export type AnchorAttributes = HTMLAttributes<HTMLAnchorElement> & {
123
+ href?: ReactiveProp<string | undefined | null>;
124
+ target?: ReactiveProp<"_blank" | "_self" | "_parent" | "_top" | string | undefined | null>;
125
+ rel?: ReactiveProp<string | undefined | null>;
126
+ download?: ReactiveProp<any>;
127
+ };
128
+
129
+ export interface VisageIntrinsicElements {
130
+ // HTML tags
131
+ div: HTMLAttributes<HTMLDivElement>;
132
+ span: HTMLAttributes<HTMLSpanElement>;
133
+ p: HTMLAttributes<HTMLParagraphElement>;
134
+ a: AnchorAttributes;
135
+ button: ButtonAttributes;
136
+ input: InputAttributes;
137
+ textarea: HTMLAttributes<HTMLTextAreaElement> & {
138
+ value?: ReactiveProp<string | number | undefined | null>;
139
+ placeholder?: ReactiveProp<string | undefined | null>;
140
+ rows?: ReactiveProp<number | undefined | null>;
141
+ cols?: ReactiveProp<number | undefined | null>;
142
+ };
143
+ select: HTMLAttributes<HTMLSelectElement> & {
144
+ value?: ReactiveProp<any>;
145
+ multiple?: ReactiveProp<boolean | undefined | null>;
146
+ };
147
+ option: HTMLAttributes<HTMLOptionElement> & {
148
+ value?: ReactiveProp<any>;
149
+ selected?: ReactiveProp<boolean | undefined | null>;
150
+ };
151
+ form: HTMLAttributes<HTMLFormElement> & {
152
+ action?: ReactiveProp<string | undefined | null>;
153
+ method?: ReactiveProp<string | undefined | null>;
154
+ };
155
+ label: HTMLAttributes<HTMLLabelElement> & {
156
+ htmlFor?: ReactiveProp<string | undefined | null>;
157
+ for?: ReactiveProp<string | undefined | null>;
158
+ };
159
+ h1: HTMLAttributes<HTMLHeadingElement>;
160
+ h2: HTMLAttributes<HTMLHeadingElement>;
161
+ h3: HTMLAttributes<HTMLHeadingElement>;
162
+ h4: HTMLAttributes<HTMLHeadingElement>;
163
+ h5: HTMLAttributes<HTMLHeadingElement>;
164
+ h6: HTMLAttributes<HTMLHeadingElement>;
165
+ header: HTMLAttributes<HTMLElement>;
166
+ footer: HTMLAttributes<HTMLElement>;
167
+ main: HTMLAttributes<HTMLElement>;
168
+ nav: HTMLAttributes<HTMLElement>;
169
+ section: HTMLAttributes<HTMLElement>;
170
+ article: HTMLAttributes<HTMLElement>;
171
+ aside: HTMLAttributes<HTMLElement>;
172
+ ul: HTMLAttributes<HTMLUListElement>;
173
+ ol: HTMLAttributes<HTMLOListElement>;
174
+ li: HTMLAttributes<HTMLLIElement>;
175
+ table: HTMLAttributes<HTMLTableElement>;
176
+ thead: HTMLAttributes<HTMLTableSectionElement>;
177
+ tbody: HTMLAttributes<HTMLTableSectionElement>;
178
+ tfoot: HTMLAttributes<HTMLTableSectionElement>;
179
+ tr: HTMLAttributes<HTMLTableRowElement>;
180
+ td: HTMLAttributes<HTMLTableCellElement>;
181
+ th: HTMLAttributes<HTMLTableCellElement>;
182
+ img: HTMLAttributes<HTMLImageElement> & {
183
+ src?: ReactiveProp<string | undefined | null>;
184
+ alt?: ReactiveProp<string | undefined | null>;
185
+ width?: ReactiveProp<number | string | undefined | null>;
186
+ height?: ReactiveProp<number | string | undefined | null>;
187
+ loading?: ReactiveProp<"lazy" | "eager" | undefined | null>;
188
+ };
189
+ iframe: HTMLAttributes<HTMLIFrameElement> & {
190
+ src?: ReactiveProp<string | undefined | null>;
191
+ title?: ReactiveProp<string | undefined | null>;
192
+ };
193
+ canvas: HTMLAttributes<HTMLCanvasElement> & {
194
+ width?: ReactiveProp<number | undefined | null>;
195
+ height?: ReactiveProp<number | undefined | null>;
196
+ };
197
+ code: HTMLAttributes<HTMLElement>;
198
+ pre: HTMLAttributes<HTMLPreElement>;
199
+ blockquote: HTMLAttributes<HTMLQuoteElement>;
200
+ strong: HTMLAttributes<HTMLElement>;
201
+ em: HTMLAttributes<HTMLElement>;
202
+ small: HTMLAttributes<HTMLElement>;
203
+ hr: HTMLAttributes<HTMLHRElement>;
204
+ br: HTMLAttributes<HTMLBRElement>;
205
+
206
+ // SVG Tags
207
+ svg: HTMLAttributes<SVGElement> & {
208
+ viewBox?: ReactiveProp<string>;
209
+ xmlns?: ReactiveProp<string>;
210
+ width?: ReactiveProp<number | string>;
211
+ height?: ReactiveProp<number | string>;
212
+ fill?: ReactiveProp<string>;
213
+ stroke?: ReactiveProp<string>;
214
+ };
215
+ path: HTMLAttributes<SVGElement> & {
216
+ d?: ReactiveProp<string>;
217
+ fill?: ReactiveProp<string>;
218
+ stroke?: ReactiveProp<string>;
219
+ strokeWidth?: ReactiveProp<number | string>;
220
+ };
221
+ circle: HTMLAttributes<SVGElement> & {
222
+ cx?: ReactiveProp<number | string>;
223
+ cy?: ReactiveProp<number | string>;
224
+ r?: ReactiveProp<number | string>;
225
+ fill?: ReactiveProp<string>;
226
+ };
227
+ rect: HTMLAttributes<SVGElement> & {
228
+ x?: ReactiveProp<number | string>;
229
+ y?: ReactiveProp<number | string>;
230
+ width?: ReactiveProp<number | string>;
231
+ height?: ReactiveProp<number | string>;
232
+ fill?: ReactiveProp<string>;
233
+ };
234
+
235
+ // Catch-all for other tags
236
+ [elemName: string]: HTMLAttributes<HTMLElement>;
237
+ }
238
+
239
+ /**
240
+ * Visage JSX Namespace Definitions
241
+ */
242
+ export namespace JSX {
243
+ /**
244
+ * Represents any valid JSX element in Visage (DOM Node, Signal, Function Getter, VNode, string, number, null, undefined).
245
+ */
246
+ export type Element = Node | Child;
247
+
248
+ export interface ElementChildrenAttribute {
249
+ children: unknown;
250
+ }
251
+
252
+ export interface IntrinsicAttributes {
253
+ key?: any;
254
+ [key: string]: any;
255
+ }
256
+
257
+ export interface IntrinsicElements extends VisageIntrinsicElements {}
258
+ }
259
+
260
+ declare global {
261
+ namespace JSX {
262
+ /**
263
+ * Represents any valid JSX element in Visage (DOM Node, Signal, Function Getter, VNode, string, number, null, undefined).
264
+ */
265
+ type Element = Node | Child;
266
+
267
+ interface ElementChildrenAttribute {
268
+ children: unknown;
269
+ }
270
+
271
+ interface IntrinsicAttributes {
272
+ key?: any;
273
+ [key: string]: any;
274
+ }
275
+
276
+ interface IntrinsicElements extends VisageIntrinsicElements {}
277
+ }
278
+ }
@@ -0,0 +1,64 @@
1
+ import { COMPUTED_BRAND, SIGNAL_BRAND } from "../signals";
2
+ import type { Mutation } from "./mutation-cache";
3
+ import { type QueryClient, useQueryClient } from "./query-client";
4
+ import type { MutateOptions, MutationOptions, MutationResult } from "./types";
5
+
6
+ export function createMutation<
7
+ TData = unknown,
8
+ TError = any,
9
+ TVariables = void,
10
+ TContext = unknown
11
+ >(
12
+ options:
13
+ | MutationOptions<TData, TError, TVariables, TContext>
14
+ | (() => MutationOptions<TData, TError, TVariables, TContext>),
15
+ client?: QueryClient
16
+ ): MutationResult<TData, TError, TVariables, TContext> {
17
+ const queryClient = useQueryClient(client);
18
+ const resolveOptions = () => (typeof options === "function" ? options() : options);
19
+
20
+ const defaults = queryClient.getDefaultOptions().mutations ?? {};
21
+ const mergedOpts = { ...defaults, ...resolveOptions() };
22
+
23
+ const mutation: Mutation<TData, TError, TVariables, TContext> =
24
+ queryClient.mutationCache.build(mergedOpts);
25
+
26
+ const mutate = (
27
+ variables: TVariables,
28
+ mutateOptions?: MutateOptions<TData, TError, TVariables, TContext>
29
+ ): void => {
30
+ mutation.execute(variables, mutateOptions).catch(() => {});
31
+ };
32
+
33
+ const mutateAsync = (
34
+ variables: TVariables,
35
+ mutateOptions?: MutateOptions<TData, TError, TVariables, TContext>
36
+ ): Promise<TData> => {
37
+ return mutation.execute(variables, mutateOptions);
38
+ };
39
+
40
+ const accessor = ((): TData | undefined => {
41
+ return mutation.data();
42
+ }) as MutationResult<TData, TError, TVariables, TContext>;
43
+
44
+ Object.defineProperties(accessor, {
45
+ [SIGNAL_BRAND]: { value: true },
46
+ [COMPUTED_BRAND]: { value: true },
47
+ value: { get: () => mutation.data() },
48
+ mutate: { value: mutate },
49
+ mutateAsync: { value: mutateAsync },
50
+ data: { get: () => mutation.data },
51
+ error: { get: () => mutation.error },
52
+ status: { get: () => mutation.status },
53
+ isIdle: { get: () => mutation.isIdle },
54
+ isPending: { get: () => mutation.isPending },
55
+ isLoading: { get: () => mutation.isLoading },
56
+ isSuccess: { get: () => mutation.isSuccess },
57
+ isError: { get: () => mutation.isError },
58
+ reset: { value: () => mutation.reset() },
59
+ variables: { get: () => mutation.variables },
60
+ submittedAt: { get: () => mutation.submittedAt }
61
+ });
62
+
63
+ return accessor;
64
+ }