@arcote.tech/arc-react 0.0.32 → 0.1.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/dist/form/field.d.ts +9 -10
- package/dist/form/form.d.ts +2 -2
- package/dist/form/index.d.ts +0 -1
- package/dist/form/message.d.ts +5 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +139 -318
- package/dist/reactModel.d.ts +10 -5
- package/dist/sqliteWasmAdapter.d.ts +4 -0
- package/package.json +1 -1
- package/dist/form/test.d.ts +0 -2
- package/dist/idb.d.ts +0 -3
package/dist/form/field.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { ArcAbstractAny } from "@arcote.tech/arc/elements/abstract";
|
|
1
|
+
import type { ArcElement } from "@arcote.tech/arc/elements/element";
|
|
3
2
|
import React from "react";
|
|
4
3
|
export type FormFieldContext = {
|
|
5
4
|
errors: any;
|
|
@@ -7,18 +6,18 @@ export type FormFieldContext = {
|
|
|
7
6
|
};
|
|
8
7
|
export declare const FormFieldContext: React.Context<FormFieldContext | null>;
|
|
9
8
|
export declare function useFormField(): FormFieldContext;
|
|
10
|
-
type Translations<E extends
|
|
11
|
-
[K in keyof ReturnType<E["validate"]>]: (data: Exclude<ReturnType<E["validate"]>[K], undefined>) => string;
|
|
12
|
-
};
|
|
13
|
-
type FormFieldProps<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
render: (field: FormFieldData<T>) => React.ReactNode;
|
|
9
|
+
type Translations<E extends ArcElement> = {
|
|
10
|
+
[K in keyof Exclude<ReturnType<E["validate"]>, false>]: (data: Exclude<Exclude<ReturnType<E["validate"]>, false>[K], undefined | false>) => string;
|
|
11
|
+
} | ((data: any) => string) | string;
|
|
12
|
+
type FormFieldProps<E extends ArcElement> = {
|
|
13
|
+
translations: Translations<E>;
|
|
14
|
+
render: (field: FormFieldData<E>) => React.ReactNode;
|
|
17
15
|
};
|
|
18
16
|
export type FormFieldData<T> = {
|
|
19
17
|
onChange: (value: any) => void;
|
|
20
18
|
value: any;
|
|
19
|
+
name: string;
|
|
21
20
|
};
|
|
22
|
-
export declare function FormField<
|
|
21
|
+
export declare function FormField<E extends ArcElement>(name: string): ({ translations, render }: FormFieldProps<E>) => import("react/jsx-dev-runtime").JSX.Element;
|
|
23
22
|
export {};
|
|
24
23
|
//# sourceMappingURL=field.d.ts.map
|
package/dist/form/form.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ArcObjectAny, type ArcObjectKeys } from "@arcote.tech/arc";
|
|
1
|
+
import { type ArcObjectAny, type ArcObjectKeys, type ArcObjectValueByKey } from "@arcote.tech/arc";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { FormField } from "./field";
|
|
4
4
|
export type FormContextValue<T extends ArcObjectAny> = {
|
|
@@ -12,7 +12,7 @@ export type FormContextValue<T extends ArcObjectAny> = {
|
|
|
12
12
|
export declare const FormContext: React.Context<FormContextValue<any> | null>;
|
|
13
13
|
export declare function Form<T extends ArcObjectAny>({ render, schema, onSubmit, }: {
|
|
14
14
|
render: (props: {
|
|
15
|
-
|
|
15
|
+
[K in ArcObjectKeys<T> as Capitalize<`${K}`>]: ReturnType<typeof FormField<ArcObjectValueByKey<T, K>>>;
|
|
16
16
|
}) => React.ReactNode;
|
|
17
17
|
schema: T;
|
|
18
18
|
onSubmit: (values: Record<ArcObjectKeys<T>, any>) => void | Promise<void>;
|
package/dist/form/index.d.ts
CHANGED
package/dist/form/message.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare
|
|
1
|
+
import { type HTMLAttributes } from "react";
|
|
2
|
+
export declare function FormMessage({ ...props }: HTMLAttributes<HTMLSpanElement>): import("react/jsx-dev-runtime").JSX.Element | null;
|
|
3
|
+
export declare namespace FormMessage {
|
|
4
|
+
var displayName: string;
|
|
5
|
+
}
|
|
3
6
|
//# sourceMappingURL=message.d.ts.map
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
useState
|
|
12
12
|
} from "react";
|
|
13
13
|
import { jsx } from "react/jsx-runtime";
|
|
14
|
-
"use client";
|
|
15
14
|
var FormContext = createContext(null);
|
|
16
15
|
function Form({
|
|
17
16
|
render,
|
|
@@ -23,7 +22,6 @@ function Form({
|
|
|
23
22
|
const [dirty, setDirty] = useState(new Set);
|
|
24
23
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
25
24
|
const validate = useCallback(() => {
|
|
26
|
-
console.log("validate", values, schema);
|
|
27
25
|
const errors2 = schema.validate(values);
|
|
28
26
|
setErrors(errors2);
|
|
29
27
|
return Object.values(errors2).some((result) => result);
|
|
@@ -43,12 +41,17 @@ function Form({
|
|
|
43
41
|
const handleSubmit = useCallback(async (e) => {
|
|
44
42
|
e.preventDefault();
|
|
45
43
|
setIsSubmitted(true);
|
|
46
|
-
validate();
|
|
47
|
-
if (!
|
|
44
|
+
const hasErrors2 = validate();
|
|
45
|
+
if (!hasErrors2) {
|
|
48
46
|
await onSubmit(values);
|
|
49
47
|
}
|
|
50
48
|
}, [schema, values, onSubmit, hasErrors]);
|
|
51
|
-
const
|
|
49
|
+
const Fields = useMemo(() => {
|
|
50
|
+
return Object.fromEntries(schema.entries().map(([key, value]) => [
|
|
51
|
+
key.charAt(0).toUpperCase() + key.slice(1),
|
|
52
|
+
FormField(key)
|
|
53
|
+
]));
|
|
54
|
+
}, [schema]);
|
|
52
55
|
const contextValue = useMemo(() => ({
|
|
53
56
|
values,
|
|
54
57
|
errors,
|
|
@@ -61,7 +64,7 @@ function Form({
|
|
|
61
64
|
value: contextValue,
|
|
62
65
|
children: /* @__PURE__ */ jsx("form", {
|
|
63
66
|
onSubmit: handleSubmit,
|
|
64
|
-
children: render(
|
|
67
|
+
children: render(Fields)
|
|
65
68
|
}, undefined, false, undefined, this)
|
|
66
69
|
}, undefined, false, undefined, this);
|
|
67
70
|
}
|
|
@@ -69,7 +72,6 @@ Form.displayName = "Form";
|
|
|
69
72
|
|
|
70
73
|
// form/field.tsx
|
|
71
74
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
72
|
-
"use client";
|
|
73
75
|
var FormFieldContext = createContext2(null);
|
|
74
76
|
function useFormField() {
|
|
75
77
|
const context = useContext(FormFieldContext);
|
|
@@ -77,45 +79,52 @@ function useFormField() {
|
|
|
77
79
|
throw new Error("useFormField must be used within a FormFieldProvider");
|
|
78
80
|
return context;
|
|
79
81
|
}
|
|
80
|
-
function FormField({
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
82
|
+
function FormField(name) {
|
|
83
|
+
return ({ translations, render }) => {
|
|
84
|
+
const form = useContext(FormContext);
|
|
85
|
+
if (!form)
|
|
86
|
+
throw new Error("FormField must be used within a Form");
|
|
87
|
+
const { values, errors, dirty, isSubmitted, setFieldValue, setFieldDirty } = form;
|
|
88
|
+
const schemaErrors = errors?.["schema"] || {};
|
|
89
|
+
const fieldErrors = schemaErrors[name] || false;
|
|
90
|
+
const value = values[name] || "";
|
|
91
|
+
const isDirty = dirty.has(name);
|
|
92
|
+
const handleChange = useCallback2((value2) => {
|
|
93
|
+
if (typeof value2 === "string") {
|
|
94
|
+
setFieldValue(name, value2);
|
|
95
|
+
} else if (value2?.target?.value !== undefined) {
|
|
96
|
+
setFieldValue(name, value2.target.value);
|
|
97
|
+
}
|
|
98
|
+
if (!isDirty) {
|
|
99
|
+
setFieldDirty(name);
|
|
100
|
+
}
|
|
101
|
+
}, [name, isDirty, setFieldValue, setFieldDirty]);
|
|
102
|
+
const errorMessages = fieldErrors ? Object.entries(fieldErrors).map(([key, value2]) => {
|
|
103
|
+
if (!value2)
|
|
104
|
+
return;
|
|
105
|
+
if (!translations)
|
|
106
|
+
return;
|
|
107
|
+
const translation = translations[key] || translations;
|
|
108
|
+
if (typeof translation === "function") {
|
|
109
|
+
return translation(value2);
|
|
110
|
+
}
|
|
111
|
+
if (typeof translation === "string") {
|
|
112
|
+
return translation;
|
|
113
|
+
}
|
|
114
|
+
}).filter(Boolean) : [];
|
|
115
|
+
const contextValue = useMemo2(() => ({
|
|
116
|
+
errors: isSubmitted ? fieldErrors : false,
|
|
117
|
+
messages: errorMessages
|
|
118
|
+
}), [fieldErrors, isSubmitted, errorMessages]);
|
|
119
|
+
return /* @__PURE__ */ jsx2(FormFieldContext.Provider, {
|
|
120
|
+
value: contextValue,
|
|
121
|
+
children: render({
|
|
122
|
+
onChange: handleChange,
|
|
123
|
+
name: name.toString(),
|
|
124
|
+
value
|
|
125
|
+
})
|
|
126
|
+
}, undefined, false, undefined, this);
|
|
127
|
+
};
|
|
119
128
|
}
|
|
120
129
|
// form/legacy_form_resolver.ts
|
|
121
130
|
function formResolver(schema) {
|
|
@@ -127,216 +136,22 @@ function formResolver(schema) {
|
|
|
127
136
|
};
|
|
128
137
|
}
|
|
129
138
|
// form/message.tsx
|
|
130
|
-
import React3 from "react";
|
|
131
139
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
132
|
-
|
|
133
|
-
var FormMessage = React3.forwardRef(({}, ref) => {
|
|
140
|
+
function FormMessage({ ...props }) {
|
|
134
141
|
const { messages } = useFormField();
|
|
135
142
|
if (messages.length === 0)
|
|
136
143
|
return null;
|
|
137
|
-
return /* @__PURE__ */ jsx3("
|
|
138
|
-
|
|
139
|
-
ref,
|
|
144
|
+
return /* @__PURE__ */ jsx3("span", {
|
|
145
|
+
...props,
|
|
140
146
|
children: messages[0]
|
|
141
147
|
}, undefined, false, undefined, this);
|
|
142
|
-
});
|
|
143
|
-
FormMessage.displayName = "FormMessage";
|
|
144
|
-
// form/test.tsx
|
|
145
|
-
import { object, string } from "@arcote.tech/arc";
|
|
146
|
-
import { jsx as jsx4, Fragment } from "react/jsx-runtime";
|
|
147
|
-
"use client";
|
|
148
|
-
function Test() {
|
|
149
|
-
const schema = object({
|
|
150
|
-
username: string().minLength(3).maxLength(10)
|
|
151
|
-
});
|
|
152
|
-
const handleSubmit = async (values) => {
|
|
153
|
-
console.log("Form submitted:", values);
|
|
154
|
-
};
|
|
155
|
-
return /* @__PURE__ */ jsx4(Form, {
|
|
156
|
-
schema,
|
|
157
|
-
onSubmit: handleSubmit,
|
|
158
|
-
render: ({ FormField: FormField2 }) => /* @__PURE__ */ jsx4("div", {
|
|
159
|
-
children: [
|
|
160
|
-
/* @__PURE__ */ jsx4(FormField2, {
|
|
161
|
-
name: "username",
|
|
162
|
-
translations: {
|
|
163
|
-
minLength: ({ minLength }) => `Username must be at least ${minLength} characters long`,
|
|
164
|
-
maxLength: ({ maxLength }) => `Username must be at most ${maxLength} characters long`
|
|
165
|
-
},
|
|
166
|
-
render: (field) => /* @__PURE__ */ jsx4(Fragment, {
|
|
167
|
-
children: [
|
|
168
|
-
/* @__PURE__ */ jsx4("input", {
|
|
169
|
-
className: "border border-gray-300 rounded-md p-2",
|
|
170
|
-
...field
|
|
171
|
-
}, undefined, false, undefined, this),
|
|
172
|
-
/* @__PURE__ */ jsx4(FormMessage, {}, undefined, false, undefined, this)
|
|
173
|
-
]
|
|
174
|
-
}, undefined, true, undefined, this)
|
|
175
|
-
}, undefined, false, undefined, this),
|
|
176
|
-
/* @__PURE__ */ jsx4("button", {
|
|
177
|
-
type: "submit",
|
|
178
|
-
children: "Submit"
|
|
179
|
-
}, undefined, false, undefined, this)
|
|
180
|
-
]
|
|
181
|
-
}, undefined, true, undefined, this)
|
|
182
|
-
}, undefined, false, undefined, this);
|
|
183
|
-
}
|
|
184
|
-
// idb.ts
|
|
185
|
-
import {
|
|
186
|
-
ArcCollection,
|
|
187
|
-
ArcIndexedCollection
|
|
188
|
-
} from "@arcote.tech/arc";
|
|
189
|
-
var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, reject) => {
|
|
190
|
-
const dbRequest = indexedDB.open(name, version);
|
|
191
|
-
dbRequest.addEventListener("error", (err) => {
|
|
192
|
-
reject(err);
|
|
193
|
-
});
|
|
194
|
-
dbRequest.addEventListener("success", (ev) => {
|
|
195
|
-
resolve(new IDBAdapter(ev.target.result));
|
|
196
|
-
});
|
|
197
|
-
dbRequest.addEventListener("upgradeneeded", (ev) => {
|
|
198
|
-
const db = ev.target.result;
|
|
199
|
-
context.elements.filter((element) => element instanceof ArcIndexedCollection || element instanceof ArcCollection).forEach((collection) => {
|
|
200
|
-
const name2 = collection.name;
|
|
201
|
-
if (db.objectStoreNames.contains(name2)) {
|
|
202
|
-
db.deleteObjectStore(collection.name);
|
|
203
|
-
}
|
|
204
|
-
const objectStore = db.createObjectStore(collection.name, {
|
|
205
|
-
keyPath: "_id"
|
|
206
|
-
});
|
|
207
|
-
if (collection instanceof ArcIndexedCollection) {
|
|
208
|
-
Object.entries(collection.indexes).forEach(([name3, keyPath]) => {
|
|
209
|
-
objectStore.createIndex(name3, keyPath, {
|
|
210
|
-
unique: false
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
if (db.objectStoreNames.contains("state")) {
|
|
216
|
-
db.deleteObjectStore("state");
|
|
217
|
-
}
|
|
218
|
-
db.createObjectStore("state", {
|
|
219
|
-
keyPath: "_id"
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
class IDBReadTransaction {
|
|
225
|
-
transaction;
|
|
226
|
-
constructor(transaction) {
|
|
227
|
-
this.transaction = transaction;
|
|
228
|
-
}
|
|
229
|
-
async findById(store, id) {
|
|
230
|
-
return new Promise((resolve) => {
|
|
231
|
-
if (!id) {
|
|
232
|
-
resolve(undefined);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
const result = this.transaction.objectStore(store).get(id);
|
|
236
|
-
result.onsuccess = (e) => {
|
|
237
|
-
resolve(e.target.result);
|
|
238
|
-
};
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
async findByIndex(store, index, data) {
|
|
242
|
-
return new Promise((resolve) => {
|
|
243
|
-
const idbIndex = this.transaction.objectStore(store).index(index);
|
|
244
|
-
const keyPath = idbIndex.keyPath;
|
|
245
|
-
let keyRange;
|
|
246
|
-
const getKey = (obj) => {
|
|
247
|
-
if (!obj)
|
|
248
|
-
return;
|
|
249
|
-
const key = keyPath.map((key2) => obj[key2]);
|
|
250
|
-
if (key.some((value) => value === undefined))
|
|
251
|
-
return;
|
|
252
|
-
return key;
|
|
253
|
-
};
|
|
254
|
-
const simpleKey = getKey(data);
|
|
255
|
-
if (!simpleKey) {
|
|
256
|
-
const lower = "$gt" in data ? getKey(data.$gt) : getKey(data.$gte);
|
|
257
|
-
const upper = "$lt" in data ? getKey(data.$lt) : getKey(data.$lte);
|
|
258
|
-
const lowerOpen = "$gt" in data;
|
|
259
|
-
const upperOpen = "$lt" in data;
|
|
260
|
-
if (lower !== undefined && upper !== undefined) {
|
|
261
|
-
keyRange = IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen);
|
|
262
|
-
} else if (lower !== undefined) {
|
|
263
|
-
keyRange = IDBKeyRange.lowerBound(lower, lowerOpen);
|
|
264
|
-
} else {
|
|
265
|
-
keyRange = IDBKeyRange.upperBound(upper, upperOpen);
|
|
266
|
-
}
|
|
267
|
-
} else {
|
|
268
|
-
keyRange = IDBKeyRange.only(simpleKey);
|
|
269
|
-
}
|
|
270
|
-
const result = idbIndex.getAll(keyRange);
|
|
271
|
-
result.onsuccess = (e) => {
|
|
272
|
-
resolve(e.target.result);
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
async findAll(store) {
|
|
277
|
-
return new Promise((resolve) => {
|
|
278
|
-
const result = this.transaction.objectStore(store).getAll();
|
|
279
|
-
result.onsuccess = (e) => {
|
|
280
|
-
resolve(e.target.result);
|
|
281
|
-
};
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
class IDBReadWriteTransaction extends IDBReadTransaction {
|
|
287
|
-
async set(store, data) {
|
|
288
|
-
return new Promise((resolve, reject) => {
|
|
289
|
-
const result = this.transaction.objectStore(store).put(data);
|
|
290
|
-
result.onsuccess = (e) => {
|
|
291
|
-
resolve();
|
|
292
|
-
};
|
|
293
|
-
result.onerror = (e) => {
|
|
294
|
-
reject(e);
|
|
295
|
-
};
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
async remove(store, id) {
|
|
299
|
-
return new Promise((resolve, reject) => {
|
|
300
|
-
const result = this.transaction.objectStore(store).delete(id);
|
|
301
|
-
result.onsuccess = (e) => {
|
|
302
|
-
resolve();
|
|
303
|
-
};
|
|
304
|
-
result.onerror = (e) => {
|
|
305
|
-
reject(e);
|
|
306
|
-
};
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
async commit() {
|
|
310
|
-
return new Promise((resolve) => {
|
|
311
|
-
this.transaction.oncomplete = () => {
|
|
312
|
-
resolve();
|
|
313
|
-
};
|
|
314
|
-
this.transaction.commit();
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
class IDBAdapter {
|
|
320
|
-
db;
|
|
321
|
-
constructor(db) {
|
|
322
|
-
this.db = db;
|
|
323
|
-
}
|
|
324
|
-
readWriteTransaction(stores) {
|
|
325
|
-
if (!stores)
|
|
326
|
-
stores = Array.from(this.db.objectStoreNames);
|
|
327
|
-
const transaction = this.db.transaction(stores, "readwrite");
|
|
328
|
-
return new IDBReadWriteTransaction(transaction);
|
|
329
|
-
}
|
|
330
|
-
readTransaction(stores) {
|
|
331
|
-
if (!stores)
|
|
332
|
-
stores = Array.from(this.db.objectStoreNames);
|
|
333
|
-
const transaction = this.db.transaction(stores, "readonly");
|
|
334
|
-
return new IDBReadTransaction(transaction);
|
|
335
|
-
}
|
|
336
148
|
}
|
|
149
|
+
FormMessage.displayName = "FormMessage";
|
|
337
150
|
// reactModel.tsx
|
|
338
151
|
import {
|
|
339
152
|
MasterDataStorage,
|
|
153
|
+
Model,
|
|
154
|
+
RemoteModelClient,
|
|
340
155
|
rtcClientFactory
|
|
341
156
|
} from "@arcote.tech/arc";
|
|
342
157
|
import {
|
|
@@ -347,127 +162,133 @@ import {
|
|
|
347
162
|
useRef,
|
|
348
163
|
useState as useState2
|
|
349
164
|
} from "react";
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
165
|
+
|
|
166
|
+
// sqliteWasmAdapter.ts
|
|
167
|
+
import {
|
|
168
|
+
createSQLiteAdapterFactory
|
|
169
|
+
} from "@arcote.tech/arc";
|
|
170
|
+
var sqliteWasmAdapterFactory = (db) => {
|
|
171
|
+
return async (context) => {
|
|
172
|
+
return createSQLiteAdapterFactory(db)(context);
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// reactModel.tsx
|
|
177
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
178
|
+
var reactModel = (arcContext, options) => {
|
|
353
179
|
const LiveModelContext = createContext3(null);
|
|
354
180
|
const LocalModelContext = createContext3(null);
|
|
355
|
-
let
|
|
181
|
+
let masterModel = null;
|
|
356
182
|
return [
|
|
357
183
|
function LiveModelProvider(props) {
|
|
358
|
-
const
|
|
184
|
+
const model = useMemo3(() => {
|
|
359
185
|
if (typeof window === "undefined")
|
|
360
186
|
return null;
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
187
|
+
if (masterModel)
|
|
188
|
+
return masterModel;
|
|
189
|
+
if ("remoteUrl" in options) {
|
|
190
|
+
const model2 = new RemoteModelClient(arcContext, options.remoteUrl, props.client, props.catchErrorCallback);
|
|
191
|
+
masterModel = model2;
|
|
192
|
+
return model2;
|
|
193
|
+
} else {
|
|
194
|
+
const dbAdapterPromise = sqliteWasmAdapterFactory(options.sqliteAdapter)(arcContext);
|
|
195
|
+
const dataStorage = new MasterDataStorage(dbAdapterPromise, rtcClientFactory(props.token), arcContext);
|
|
196
|
+
const model2 = new Model(arcContext, dataStorage, props.client, props.catchErrorCallback);
|
|
197
|
+
masterModel = model2;
|
|
198
|
+
return model2;
|
|
199
|
+
}
|
|
200
|
+
}, [arcContext, options, props.client]);
|
|
366
201
|
const [syncProgress, setSyncProgress] = useState2([]);
|
|
367
202
|
const [syncDone, setSyncDone] = useState2(false);
|
|
368
203
|
useEffect2(() => {
|
|
369
|
-
if (typeof window === "undefined" || !
|
|
204
|
+
if (typeof window === "undefined" || !model)
|
|
370
205
|
return;
|
|
371
206
|
const sync = async () => {
|
|
372
|
-
|
|
207
|
+
if (!("dataStorage" in model))
|
|
208
|
+
return setSyncDone(true);
|
|
209
|
+
await model.dataStorage.sync(({ store, size }) => {
|
|
373
210
|
setSyncProgress((prev) => [...prev, { store, size }]);
|
|
374
211
|
});
|
|
375
212
|
setSyncDone(true);
|
|
376
213
|
};
|
|
377
214
|
sync();
|
|
378
|
-
}, [
|
|
379
|
-
if (!
|
|
380
|
-
return /* @__PURE__ */
|
|
215
|
+
}, [model]);
|
|
216
|
+
if (!model || !syncDone)
|
|
217
|
+
return props.syncView ? /* @__PURE__ */ jsx4(props.syncView, {
|
|
381
218
|
progress: syncProgress
|
|
382
|
-
}, undefined, false, undefined, this);
|
|
383
|
-
return /* @__PURE__ */
|
|
384
|
-
value:
|
|
385
|
-
dataStorage,
|
|
386
|
-
client: props.client,
|
|
387
|
-
catchErrorCallback: props.catchErrorCallback
|
|
388
|
-
},
|
|
219
|
+
}, undefined, false, undefined, this) : null;
|
|
220
|
+
return /* @__PURE__ */ jsx4(LiveModelContext.Provider, {
|
|
221
|
+
value: model,
|
|
389
222
|
children: props.children
|
|
390
223
|
}, undefined, false, undefined, this);
|
|
391
224
|
},
|
|
392
225
|
function LocalModelProvider({ children }) {
|
|
393
|
-
const
|
|
394
|
-
if (!
|
|
226
|
+
const parentModel = useContext2(LiveModelContext);
|
|
227
|
+
if (!parentModel || !(parentModel instanceof Model)) {
|
|
395
228
|
throw new Error("LocalModelProvider must be used within a LiveModelProvider");
|
|
396
229
|
}
|
|
397
|
-
const [
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return /* @__PURE__ */ jsx5(LocalModelContext.Provider, {
|
|
401
|
-
value: {
|
|
402
|
-
dataStorage: localContext.dataStorage,
|
|
403
|
-
client: parentContext.client,
|
|
404
|
-
catchErrorCallback: parentContext.catchErrorCallback
|
|
405
|
-
},
|
|
230
|
+
const [localModel] = useState2(() => parentModel.fork());
|
|
231
|
+
return /* @__PURE__ */ jsx4(LocalModelContext.Provider, {
|
|
232
|
+
value: localModel,
|
|
406
233
|
children
|
|
407
234
|
}, undefined, false, undefined, this);
|
|
408
235
|
},
|
|
409
236
|
function useQuery(queryBuilderFn, dependencies = []) {
|
|
410
|
-
const
|
|
411
|
-
if (!
|
|
237
|
+
const model = useContext2(LocalModelContext) || useContext2(LiveModelContext);
|
|
238
|
+
if (!model) {
|
|
412
239
|
throw new Error("useQuery must be used within a ModelProvider");
|
|
413
240
|
}
|
|
414
241
|
const [result, setResult] = useState2(null);
|
|
415
242
|
const [loading, setLoading] = useState2(true);
|
|
416
|
-
const
|
|
243
|
+
const unsubscribeRef = useRef(null);
|
|
417
244
|
useEffect2(() => {
|
|
418
|
-
if (
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
const runQuery = async () => {
|
|
424
|
-
const result2 = await query.run(context.dataStorage, (newResult) => {
|
|
425
|
-
setResult(newResult);
|
|
426
|
-
setLoading(false);
|
|
427
|
-
});
|
|
428
|
-
setResult(result2);
|
|
245
|
+
if (unsubscribeRef.current) {
|
|
246
|
+
unsubscribeRef.current();
|
|
247
|
+
}
|
|
248
|
+
const { unsubscribe, result: result2 } = model.subscribe(queryBuilderFn, (newResult) => {
|
|
249
|
+
setResult(newResult);
|
|
429
250
|
setLoading(false);
|
|
430
|
-
};
|
|
431
|
-
|
|
251
|
+
});
|
|
252
|
+
unsubscribeRef.current = unsubscribe;
|
|
253
|
+
result2.then(() => {
|
|
254
|
+
setLoading(false);
|
|
255
|
+
});
|
|
432
256
|
return () => {
|
|
433
|
-
|
|
434
|
-
|
|
257
|
+
if (unsubscribeRef.current) {
|
|
258
|
+
unsubscribeRef.current();
|
|
259
|
+
unsubscribeRef.current = null;
|
|
260
|
+
}
|
|
435
261
|
};
|
|
436
|
-
}, [
|
|
262
|
+
}, [model, ...dependencies]);
|
|
437
263
|
return [result, loading];
|
|
438
264
|
},
|
|
439
265
|
function useCommands() {
|
|
440
|
-
const
|
|
441
|
-
if (!
|
|
442
|
-
throw new Error("
|
|
266
|
+
const model = useContext2(LocalModelContext) || useContext2(LiveModelContext);
|
|
267
|
+
if (!model) {
|
|
268
|
+
throw new Error("useCommands must be used within a ModelProvider");
|
|
443
269
|
}
|
|
444
|
-
return
|
|
270
|
+
return model.commands();
|
|
445
271
|
},
|
|
446
|
-
async function query(queryBuilderFn,
|
|
447
|
-
if (!
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
throw new Error("dataStorage not found");
|
|
453
|
-
const result = await query.run(datastorage);
|
|
454
|
-
return result;
|
|
272
|
+
async function query(queryBuilderFn, model) {
|
|
273
|
+
if (!model)
|
|
274
|
+
model = masterModel;
|
|
275
|
+
if (!model)
|
|
276
|
+
throw new Error("Model not found");
|
|
277
|
+
return model.query(queryBuilderFn);
|
|
455
278
|
},
|
|
456
|
-
function
|
|
457
|
-
const
|
|
458
|
-
if (!
|
|
279
|
+
function useLocalModel() {
|
|
280
|
+
const model = useContext2(LocalModelContext);
|
|
281
|
+
if (!model) {
|
|
459
282
|
return null;
|
|
460
283
|
}
|
|
461
|
-
return
|
|
284
|
+
return model;
|
|
462
285
|
}
|
|
463
286
|
];
|
|
464
287
|
};
|
|
465
288
|
export {
|
|
466
289
|
useFormField,
|
|
467
290
|
reactModel,
|
|
468
|
-
idbAdapterFactory,
|
|
469
291
|
formResolver,
|
|
470
|
-
Test,
|
|
471
292
|
FormMessage,
|
|
472
293
|
FormFieldContext,
|
|
473
294
|
FormField,
|
|
@@ -475,4 +296,4 @@ export {
|
|
|
475
296
|
Form
|
|
476
297
|
};
|
|
477
298
|
|
|
478
|
-
//# debugId=
|
|
299
|
+
//# debugId=F5FEB20267C5EE2264756E2164756E21
|
package/dist/reactModel.d.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ForkedModel, type ArcContextAny, type IArcQueryBuilder, type ModelBase, type QueryBuilderFunctionResult, type QueryFactoryFunction, type UnaryFunction } from "@arcote.tech/arc";
|
|
2
|
+
import type { SQLiteDatabase } from "@arcote.tech/arc";
|
|
3
|
+
export declare const reactModel: <C extends ArcContextAny>(arcContext: C, options: {
|
|
4
|
+
sqliteAdapter: SQLiteDatabase;
|
|
5
|
+
} | {
|
|
6
|
+
remoteUrl: string;
|
|
7
|
+
}) => readonly [(props: {
|
|
3
8
|
children: React.ReactNode;
|
|
4
9
|
client: string;
|
|
5
10
|
token: string;
|
|
6
|
-
syncView
|
|
11
|
+
syncView?: React.ComponentType<{
|
|
7
12
|
progress: {
|
|
8
13
|
store: string;
|
|
9
14
|
size: number;
|
|
10
15
|
}[];
|
|
11
16
|
}>;
|
|
12
17
|
catchErrorCallback: (error: any) => void;
|
|
13
|
-
}) => import("react/jsx-dev-runtime").JSX.Element, ({ children }: {
|
|
18
|
+
}) => import("react/jsx-dev-runtime").JSX.Element | null, ({ children }: {
|
|
14
19
|
children: React.ReactNode;
|
|
15
|
-
}) => import("react/jsx-dev-runtime").JSX.Element, <
|
|
20
|
+
}) => import("react/jsx-dev-runtime").JSX.Element, <Q extends IArcQueryBuilder>(queryBuilderFn: UnaryFunction<ReturnType<C["queryBuilder"]>, Q>, dependencies?: any[]) => [ReturnType<Q["toQuery"]>["lastResult"], boolean], () => ReturnType<C["commandsClient"]>, <QueryBuilderFn extends QueryFactoryFunction<C>>(queryBuilderFn: QueryBuilderFn, model?: ModelBase<C> | null) => Promise<QueryBuilderFunctionResult<QueryBuilderFn>>, () => ForkedModel<C> | null];
|
|
16
21
|
//# sourceMappingURL=reactModel.d.ts.map
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "0.0
|
|
7
|
+
"version": "0.1.0",
|
|
8
8
|
"private": false,
|
|
9
9
|
"author": "Przemysław Krasiński [arcote.tech]",
|
|
10
10
|
"description": "React client for the Arc framework, providing utilities for querying data and executing commands, enhancing the development of reactive and efficient user interfaces.",
|
package/dist/form/test.d.ts
DELETED
package/dist/idb.d.ts
DELETED