@arcote.tech/arc-react 0.0.33 → 0.1.1
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 +147 -313
- 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
|
@@ -22,7 +22,6 @@ function Form({
|
|
|
22
22
|
const [dirty, setDirty] = useState(new Set);
|
|
23
23
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
24
24
|
const validate = useCallback(() => {
|
|
25
|
-
console.log("validate", values, schema);
|
|
26
25
|
const errors2 = schema.validate(values);
|
|
27
26
|
setErrors(errors2);
|
|
28
27
|
return Object.values(errors2).some((result) => result);
|
|
@@ -42,12 +41,17 @@ function Form({
|
|
|
42
41
|
const handleSubmit = useCallback(async (e) => {
|
|
43
42
|
e.preventDefault();
|
|
44
43
|
setIsSubmitted(true);
|
|
45
|
-
validate();
|
|
46
|
-
if (!
|
|
44
|
+
const hasErrors2 = validate();
|
|
45
|
+
if (!hasErrors2) {
|
|
47
46
|
await onSubmit(values);
|
|
48
47
|
}
|
|
49
48
|
}, [schema, values, onSubmit, hasErrors]);
|
|
50
|
-
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]);
|
|
51
55
|
const contextValue = useMemo(() => ({
|
|
52
56
|
values,
|
|
53
57
|
errors,
|
|
@@ -60,7 +64,7 @@ function Form({
|
|
|
60
64
|
value: contextValue,
|
|
61
65
|
children: /* @__PURE__ */ jsx("form", {
|
|
62
66
|
onSubmit: handleSubmit,
|
|
63
|
-
children: render(
|
|
67
|
+
children: render(Fields)
|
|
64
68
|
}, undefined, false, undefined, this)
|
|
65
69
|
}, undefined, false, undefined, this);
|
|
66
70
|
}
|
|
@@ -75,45 +79,52 @@ function useFormField() {
|
|
|
75
79
|
throw new Error("useFormField must be used within a FormFieldProvider");
|
|
76
80
|
return context;
|
|
77
81
|
}
|
|
78
|
-
function FormField({
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
+
};
|
|
117
128
|
}
|
|
118
129
|
// form/legacy_form_resolver.ts
|
|
119
130
|
function formResolver(schema) {
|
|
@@ -125,214 +136,22 @@ function formResolver(schema) {
|
|
|
125
136
|
};
|
|
126
137
|
}
|
|
127
138
|
// form/message.tsx
|
|
128
|
-
import React3 from "react";
|
|
129
139
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
130
|
-
|
|
140
|
+
function FormMessage({ ...props }) {
|
|
131
141
|
const { messages } = useFormField();
|
|
132
142
|
if (messages.length === 0)
|
|
133
143
|
return null;
|
|
134
|
-
return /* @__PURE__ */ jsx3("
|
|
135
|
-
|
|
136
|
-
ref,
|
|
144
|
+
return /* @__PURE__ */ jsx3("span", {
|
|
145
|
+
...props,
|
|
137
146
|
children: messages[0]
|
|
138
147
|
}, undefined, false, undefined, this);
|
|
139
|
-
});
|
|
140
|
-
FormMessage.displayName = "FormMessage";
|
|
141
|
-
// form/test.tsx
|
|
142
|
-
import { object, string } from "@arcote.tech/arc";
|
|
143
|
-
import { jsx as jsx4, Fragment } from "react/jsx-runtime";
|
|
144
|
-
function Test() {
|
|
145
|
-
const schema = object({
|
|
146
|
-
username: string().minLength(3).maxLength(10)
|
|
147
|
-
});
|
|
148
|
-
const handleSubmit = async (values) => {
|
|
149
|
-
console.log("Form submitted:", values);
|
|
150
|
-
};
|
|
151
|
-
return /* @__PURE__ */ jsx4(Form, {
|
|
152
|
-
schema,
|
|
153
|
-
onSubmit: handleSubmit,
|
|
154
|
-
render: ({ FormField: FormField2 }) => /* @__PURE__ */ jsx4("div", {
|
|
155
|
-
children: [
|
|
156
|
-
/* @__PURE__ */ jsx4(FormField2, {
|
|
157
|
-
name: "username",
|
|
158
|
-
translations: {
|
|
159
|
-
minLength: ({ minLength }) => `Username must be at least ${minLength} characters long`,
|
|
160
|
-
maxLength: ({ maxLength }) => `Username must be at most ${maxLength} characters long`
|
|
161
|
-
},
|
|
162
|
-
render: (field) => /* @__PURE__ */ jsx4(Fragment, {
|
|
163
|
-
children: [
|
|
164
|
-
/* @__PURE__ */ jsx4("input", {
|
|
165
|
-
className: "border border-gray-300 rounded-md p-2",
|
|
166
|
-
...field
|
|
167
|
-
}, undefined, false, undefined, this),
|
|
168
|
-
/* @__PURE__ */ jsx4(FormMessage, {}, undefined, false, undefined, this)
|
|
169
|
-
]
|
|
170
|
-
}, undefined, true, undefined, this)
|
|
171
|
-
}, undefined, false, undefined, this),
|
|
172
|
-
/* @__PURE__ */ jsx4("button", {
|
|
173
|
-
type: "submit",
|
|
174
|
-
children: "Submit"
|
|
175
|
-
}, undefined, false, undefined, this)
|
|
176
|
-
]
|
|
177
|
-
}, undefined, true, undefined, this)
|
|
178
|
-
}, undefined, false, undefined, this);
|
|
179
|
-
}
|
|
180
|
-
// idb.ts
|
|
181
|
-
import {
|
|
182
|
-
ArcCollection,
|
|
183
|
-
ArcIndexedCollection
|
|
184
|
-
} from "@arcote.tech/arc";
|
|
185
|
-
var idbAdapterFactory = (name, version) => (context) => new Promise((resolve, reject) => {
|
|
186
|
-
const dbRequest = indexedDB.open(name, version);
|
|
187
|
-
dbRequest.addEventListener("error", (err) => {
|
|
188
|
-
reject(err);
|
|
189
|
-
});
|
|
190
|
-
dbRequest.addEventListener("success", (ev) => {
|
|
191
|
-
resolve(new IDBAdapter(ev.target.result));
|
|
192
|
-
});
|
|
193
|
-
dbRequest.addEventListener("upgradeneeded", (ev) => {
|
|
194
|
-
const db = ev.target.result;
|
|
195
|
-
context.elements.filter((element) => element instanceof ArcIndexedCollection || element instanceof ArcCollection).forEach((collection) => {
|
|
196
|
-
const name2 = collection.name;
|
|
197
|
-
if (db.objectStoreNames.contains(name2)) {
|
|
198
|
-
db.deleteObjectStore(collection.name);
|
|
199
|
-
}
|
|
200
|
-
const objectStore = db.createObjectStore(collection.name, {
|
|
201
|
-
keyPath: "_id"
|
|
202
|
-
});
|
|
203
|
-
if (collection instanceof ArcIndexedCollection) {
|
|
204
|
-
Object.entries(collection.indexes).forEach(([name3, keyPath]) => {
|
|
205
|
-
objectStore.createIndex(name3, keyPath, {
|
|
206
|
-
unique: false
|
|
207
|
-
});
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
if (db.objectStoreNames.contains("state")) {
|
|
212
|
-
db.deleteObjectStore("state");
|
|
213
|
-
}
|
|
214
|
-
db.createObjectStore("state", {
|
|
215
|
-
keyPath: "_id"
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
class IDBReadTransaction {
|
|
221
|
-
transaction;
|
|
222
|
-
constructor(transaction) {
|
|
223
|
-
this.transaction = transaction;
|
|
224
|
-
}
|
|
225
|
-
async findById(store, id) {
|
|
226
|
-
return new Promise((resolve) => {
|
|
227
|
-
if (!id) {
|
|
228
|
-
resolve(undefined);
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
const result = this.transaction.objectStore(store).get(id);
|
|
232
|
-
result.onsuccess = (e) => {
|
|
233
|
-
resolve(e.target.result);
|
|
234
|
-
};
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
async findByIndex(store, index, data) {
|
|
238
|
-
return new Promise((resolve) => {
|
|
239
|
-
const idbIndex = this.transaction.objectStore(store).index(index);
|
|
240
|
-
const keyPath = idbIndex.keyPath;
|
|
241
|
-
let keyRange;
|
|
242
|
-
const getKey = (obj) => {
|
|
243
|
-
if (!obj)
|
|
244
|
-
return;
|
|
245
|
-
const key = keyPath.map((key2) => obj[key2]);
|
|
246
|
-
if (key.some((value) => value === undefined))
|
|
247
|
-
return;
|
|
248
|
-
return key;
|
|
249
|
-
};
|
|
250
|
-
const simpleKey = getKey(data);
|
|
251
|
-
if (!simpleKey) {
|
|
252
|
-
const lower = "$gt" in data ? getKey(data.$gt) : getKey(data.$gte);
|
|
253
|
-
const upper = "$lt" in data ? getKey(data.$lt) : getKey(data.$lte);
|
|
254
|
-
const lowerOpen = "$gt" in data;
|
|
255
|
-
const upperOpen = "$lt" in data;
|
|
256
|
-
if (lower !== undefined && upper !== undefined) {
|
|
257
|
-
keyRange = IDBKeyRange.bound(lower, upper, lowerOpen, upperOpen);
|
|
258
|
-
} else if (lower !== undefined) {
|
|
259
|
-
keyRange = IDBKeyRange.lowerBound(lower, lowerOpen);
|
|
260
|
-
} else {
|
|
261
|
-
keyRange = IDBKeyRange.upperBound(upper, upperOpen);
|
|
262
|
-
}
|
|
263
|
-
} else {
|
|
264
|
-
keyRange = IDBKeyRange.only(simpleKey);
|
|
265
|
-
}
|
|
266
|
-
const result = idbIndex.getAll(keyRange);
|
|
267
|
-
result.onsuccess = (e) => {
|
|
268
|
-
resolve(e.target.result);
|
|
269
|
-
};
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
async findAll(store) {
|
|
273
|
-
return new Promise((resolve) => {
|
|
274
|
-
const result = this.transaction.objectStore(store).getAll();
|
|
275
|
-
result.onsuccess = (e) => {
|
|
276
|
-
resolve(e.target.result);
|
|
277
|
-
};
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
class IDBReadWriteTransaction extends IDBReadTransaction {
|
|
283
|
-
async set(store, data) {
|
|
284
|
-
return new Promise((resolve, reject) => {
|
|
285
|
-
const result = this.transaction.objectStore(store).put(data);
|
|
286
|
-
result.onsuccess = (e) => {
|
|
287
|
-
resolve();
|
|
288
|
-
};
|
|
289
|
-
result.onerror = (e) => {
|
|
290
|
-
reject(e);
|
|
291
|
-
};
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
async remove(store, id) {
|
|
295
|
-
return new Promise((resolve, reject) => {
|
|
296
|
-
const result = this.transaction.objectStore(store).delete(id);
|
|
297
|
-
result.onsuccess = (e) => {
|
|
298
|
-
resolve();
|
|
299
|
-
};
|
|
300
|
-
result.onerror = (e) => {
|
|
301
|
-
reject(e);
|
|
302
|
-
};
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
async commit() {
|
|
306
|
-
return new Promise((resolve) => {
|
|
307
|
-
this.transaction.oncomplete = () => {
|
|
308
|
-
resolve();
|
|
309
|
-
};
|
|
310
|
-
this.transaction.commit();
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
class IDBAdapter {
|
|
316
|
-
db;
|
|
317
|
-
constructor(db) {
|
|
318
|
-
this.db = db;
|
|
319
|
-
}
|
|
320
|
-
readWriteTransaction(stores) {
|
|
321
|
-
if (!stores)
|
|
322
|
-
stores = Array.from(this.db.objectStoreNames);
|
|
323
|
-
const transaction = this.db.transaction(stores, "readwrite");
|
|
324
|
-
return new IDBReadWriteTransaction(transaction);
|
|
325
|
-
}
|
|
326
|
-
readTransaction(stores) {
|
|
327
|
-
if (!stores)
|
|
328
|
-
stores = Array.from(this.db.objectStoreNames);
|
|
329
|
-
const transaction = this.db.transaction(stores, "readonly");
|
|
330
|
-
return new IDBReadTransaction(transaction);
|
|
331
|
-
}
|
|
332
148
|
}
|
|
149
|
+
FormMessage.displayName = "FormMessage";
|
|
333
150
|
// reactModel.tsx
|
|
334
151
|
import {
|
|
335
152
|
MasterDataStorage,
|
|
153
|
+
Model,
|
|
154
|
+
RemoteModelClient,
|
|
336
155
|
rtcClientFactory
|
|
337
156
|
} from "@arcote.tech/arc";
|
|
338
157
|
import {
|
|
@@ -343,126 +162,141 @@ import {
|
|
|
343
162
|
useRef,
|
|
344
163
|
useState as useState2
|
|
345
164
|
} from "react";
|
|
346
|
-
|
|
347
|
-
|
|
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 = (arcContextPromise, options) => {
|
|
348
179
|
const LiveModelContext = createContext3(null);
|
|
349
180
|
const LocalModelContext = createContext3(null);
|
|
350
|
-
let
|
|
181
|
+
let masterModel = null;
|
|
351
182
|
return [
|
|
352
183
|
function LiveModelProvider(props) {
|
|
353
|
-
const
|
|
184
|
+
const [context, setContext] = useState2(null);
|
|
185
|
+
useEffect2(() => {
|
|
186
|
+
arcContextPromise.then((arcContext) => {
|
|
187
|
+
setContext(arcContext);
|
|
188
|
+
});
|
|
189
|
+
}, [arcContextPromise]);
|
|
190
|
+
const model = useMemo3(() => {
|
|
354
191
|
if (typeof window === "undefined")
|
|
355
192
|
return null;
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
193
|
+
if (masterModel)
|
|
194
|
+
return masterModel;
|
|
195
|
+
if (!context)
|
|
196
|
+
return null;
|
|
197
|
+
if ("remoteUrl" in options) {
|
|
198
|
+
const model2 = new RemoteModelClient(context, options.remoteUrl, props.client, props.catchErrorCallback);
|
|
199
|
+
masterModel = model2;
|
|
200
|
+
return model2;
|
|
201
|
+
} else {
|
|
202
|
+
const dbAdapterPromise = sqliteWasmAdapterFactory(options.sqliteAdapter)(context);
|
|
203
|
+
const dataStorage = new MasterDataStorage(dbAdapterPromise, rtcClientFactory(props.token), context);
|
|
204
|
+
const model2 = new Model(context, dataStorage, props.client, props.catchErrorCallback);
|
|
205
|
+
masterModel = model2;
|
|
206
|
+
return model2;
|
|
207
|
+
}
|
|
208
|
+
}, [context, options, props.client]);
|
|
361
209
|
const [syncProgress, setSyncProgress] = useState2([]);
|
|
362
210
|
const [syncDone, setSyncDone] = useState2(false);
|
|
363
211
|
useEffect2(() => {
|
|
364
|
-
if (typeof window === "undefined" || !
|
|
212
|
+
if (typeof window === "undefined" || !model)
|
|
365
213
|
return;
|
|
366
214
|
const sync = async () => {
|
|
367
|
-
|
|
215
|
+
if (!("dataStorage" in model))
|
|
216
|
+
return setSyncDone(true);
|
|
217
|
+
await model.dataStorage.sync(({ store, size }) => {
|
|
368
218
|
setSyncProgress((prev) => [...prev, { store, size }]);
|
|
369
219
|
});
|
|
370
220
|
setSyncDone(true);
|
|
371
221
|
};
|
|
372
222
|
sync();
|
|
373
|
-
}, [
|
|
374
|
-
if (!
|
|
375
|
-
return /* @__PURE__ */
|
|
223
|
+
}, [model]);
|
|
224
|
+
if (!model || !syncDone)
|
|
225
|
+
return props.syncView ? /* @__PURE__ */ jsx4(props.syncView, {
|
|
376
226
|
progress: syncProgress
|
|
377
|
-
}, undefined, false, undefined, this);
|
|
378
|
-
return /* @__PURE__ */
|
|
379
|
-
value:
|
|
380
|
-
dataStorage,
|
|
381
|
-
client: props.client,
|
|
382
|
-
catchErrorCallback: props.catchErrorCallback
|
|
383
|
-
},
|
|
227
|
+
}, undefined, false, undefined, this) : null;
|
|
228
|
+
return /* @__PURE__ */ jsx4(LiveModelContext.Provider, {
|
|
229
|
+
value: model,
|
|
384
230
|
children: props.children
|
|
385
231
|
}, undefined, false, undefined, this);
|
|
386
232
|
},
|
|
387
233
|
function LocalModelProvider({ children }) {
|
|
388
|
-
const
|
|
389
|
-
if (!
|
|
234
|
+
const parentModel = useContext2(LiveModelContext);
|
|
235
|
+
if (!parentModel || !(parentModel instanceof Model)) {
|
|
390
236
|
throw new Error("LocalModelProvider must be used within a LiveModelProvider");
|
|
391
237
|
}
|
|
392
|
-
const [
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
return /* @__PURE__ */ jsx5(LocalModelContext.Provider, {
|
|
396
|
-
value: {
|
|
397
|
-
dataStorage: localContext.dataStorage,
|
|
398
|
-
client: parentContext.client,
|
|
399
|
-
catchErrorCallback: parentContext.catchErrorCallback
|
|
400
|
-
},
|
|
238
|
+
const [localModel] = useState2(() => parentModel.fork());
|
|
239
|
+
return /* @__PURE__ */ jsx4(LocalModelContext.Provider, {
|
|
240
|
+
value: localModel,
|
|
401
241
|
children
|
|
402
242
|
}, undefined, false, undefined, this);
|
|
403
243
|
},
|
|
404
244
|
function useQuery(queryBuilderFn, dependencies = []) {
|
|
405
|
-
const
|
|
406
|
-
if (!
|
|
245
|
+
const model = useContext2(LocalModelContext) || useContext2(LiveModelContext);
|
|
246
|
+
if (!model) {
|
|
407
247
|
throw new Error("useQuery must be used within a ModelProvider");
|
|
408
248
|
}
|
|
409
249
|
const [result, setResult] = useState2(null);
|
|
410
250
|
const [loading, setLoading] = useState2(true);
|
|
411
|
-
const
|
|
251
|
+
const unsubscribeRef = useRef(null);
|
|
412
252
|
useEffect2(() => {
|
|
413
|
-
if (
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
const runQuery = async () => {
|
|
419
|
-
const result2 = await query.run(context.dataStorage, (newResult) => {
|
|
420
|
-
setResult(newResult);
|
|
421
|
-
setLoading(false);
|
|
422
|
-
});
|
|
423
|
-
setResult(result2);
|
|
253
|
+
if (unsubscribeRef.current) {
|
|
254
|
+
unsubscribeRef.current();
|
|
255
|
+
}
|
|
256
|
+
const { unsubscribe, result: result2 } = model.subscribe(queryBuilderFn, (newResult) => {
|
|
257
|
+
setResult(newResult);
|
|
424
258
|
setLoading(false);
|
|
425
|
-
};
|
|
426
|
-
|
|
259
|
+
});
|
|
260
|
+
unsubscribeRef.current = unsubscribe;
|
|
261
|
+
result2.then(() => {
|
|
262
|
+
setLoading(false);
|
|
263
|
+
});
|
|
427
264
|
return () => {
|
|
428
|
-
|
|
429
|
-
|
|
265
|
+
if (unsubscribeRef.current) {
|
|
266
|
+
unsubscribeRef.current();
|
|
267
|
+
unsubscribeRef.current = null;
|
|
268
|
+
}
|
|
430
269
|
};
|
|
431
|
-
}, [
|
|
270
|
+
}, [model, ...dependencies]);
|
|
432
271
|
return [result, loading];
|
|
433
272
|
},
|
|
434
273
|
function useCommands() {
|
|
435
|
-
const
|
|
436
|
-
if (!
|
|
437
|
-
throw new Error("
|
|
274
|
+
const model = useContext2(LocalModelContext) || useContext2(LiveModelContext);
|
|
275
|
+
if (!model) {
|
|
276
|
+
throw new Error("useCommands must be used within a ModelProvider");
|
|
438
277
|
}
|
|
439
|
-
return
|
|
278
|
+
return model.commands();
|
|
440
279
|
},
|
|
441
|
-
async function query(queryBuilderFn,
|
|
442
|
-
if (!
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
throw new Error("dataStorage not found");
|
|
448
|
-
const result = await query.run(datastorage);
|
|
449
|
-
return result;
|
|
280
|
+
async function query(queryBuilderFn, model) {
|
|
281
|
+
if (!model)
|
|
282
|
+
model = masterModel;
|
|
283
|
+
if (!model)
|
|
284
|
+
throw new Error("Model not found");
|
|
285
|
+
return model.query(queryBuilderFn);
|
|
450
286
|
},
|
|
451
|
-
function
|
|
452
|
-
const
|
|
453
|
-
if (!
|
|
287
|
+
function useLocalModel() {
|
|
288
|
+
const model = useContext2(LocalModelContext);
|
|
289
|
+
if (!model) {
|
|
454
290
|
return null;
|
|
455
291
|
}
|
|
456
|
-
return
|
|
292
|
+
return model;
|
|
457
293
|
}
|
|
458
294
|
];
|
|
459
295
|
};
|
|
460
296
|
export {
|
|
461
297
|
useFormField,
|
|
462
298
|
reactModel,
|
|
463
|
-
idbAdapterFactory,
|
|
464
299
|
formResolver,
|
|
465
|
-
Test,
|
|
466
300
|
FormMessage,
|
|
467
301
|
FormFieldContext,
|
|
468
302
|
FormField,
|
|
@@ -470,4 +304,4 @@ export {
|
|
|
470
304
|
Form
|
|
471
305
|
};
|
|
472
306
|
|
|
473
|
-
//# debugId=
|
|
307
|
+
//# debugId=1DFCDB435242322064756E2164756E21
|
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>(arcContextPromise: Promise<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.
|
|
7
|
+
"version": "0.1.1",
|
|
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