@pyreon/form 0.11.5 → 0.11.7

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.
@@ -1,6 +1,6 @@
1
- import { effect } from "@pyreon/reactivity"
2
- import { mount } from "@pyreon/runtime-dom"
3
- import type { FormState } from "../index"
1
+ import { effect } from '@pyreon/reactivity'
2
+ import { mount } from '@pyreon/runtime-dom'
3
+ import type { FormState } from '../index'
4
4
  import {
5
5
  FormProvider,
6
6
  useFieldArray,
@@ -8,7 +8,7 @@ import {
8
8
  useFormContext,
9
9
  useFormState,
10
10
  useWatch,
11
- } from "../index"
11
+ } from '../index'
12
12
 
13
13
  // ─── Helpers ──────────────────────────────────────────────────────────────────
14
14
 
@@ -19,7 +19,7 @@ function Capture<T>({ fn }: { fn: () => T }) {
19
19
 
20
20
  function mountWith<T>(fn: () => T): { result: T; unmount: () => void } {
21
21
  let result: T | undefined
22
- const el = document.createElement("div")
22
+ const el = document.createElement('div')
23
23
  document.body.appendChild(el)
24
24
  const unmount = mount(
25
25
  <Capture
@@ -40,87 +40,87 @@ function mountWith<T>(fn: () => T): { result: T; unmount: () => void } {
40
40
 
41
41
  // ─── useFieldArray — additional operations ───────────────────────────────────
42
42
 
43
- describe("useFieldArray — additional operations", () => {
44
- it("append multiple items sequentially", () => {
43
+ describe('useFieldArray — additional operations', () => {
44
+ it('append multiple items sequentially', () => {
45
45
  const { result: arr, unmount } = mountWith(() => useFieldArray<string>([]))
46
46
 
47
- arr.append("a")
48
- arr.append("b")
49
- arr.append("c")
50
- expect(arr.values()).toEqual(["a", "b", "c"])
47
+ arr.append('a')
48
+ arr.append('b')
49
+ arr.append('c')
50
+ expect(arr.values()).toEqual(['a', 'b', 'c'])
51
51
  expect(arr.length()).toBe(3)
52
52
  unmount()
53
53
  })
54
54
 
55
- it("remove first item shifts remaining", () => {
56
- const { result: arr, unmount } = mountWith(() => useFieldArray(["x", "y", "z"]))
55
+ it('remove first item shifts remaining', () => {
56
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['x', 'y', 'z']))
57
57
 
58
58
  arr.remove(0)
59
- expect(arr.values()).toEqual(["y", "z"])
59
+ expect(arr.values()).toEqual(['y', 'z'])
60
60
  expect(arr.length()).toBe(2)
61
61
  unmount()
62
62
  })
63
63
 
64
- it("remove last item", () => {
65
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c"]))
64
+ it('remove last item', () => {
65
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c']))
66
66
 
67
67
  arr.remove(2)
68
- expect(arr.values()).toEqual(["a", "b"])
68
+ expect(arr.values()).toEqual(['a', 'b'])
69
69
  unmount()
70
70
  })
71
71
 
72
- it("move item forward (lower to higher index)", () => {
73
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c", "d"]))
72
+ it('move item forward (lower to higher index)', () => {
73
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c', 'd']))
74
74
 
75
75
  arr.move(1, 3) // move "b" from index 1 to index 3
76
- expect(arr.values()).toEqual(["a", "c", "d", "b"])
76
+ expect(arr.values()).toEqual(['a', 'c', 'd', 'b'])
77
77
  unmount()
78
78
  })
79
79
 
80
- it("move item backward (higher to lower index)", () => {
81
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c", "d"]))
80
+ it('move item backward (higher to lower index)', () => {
81
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c', 'd']))
82
82
 
83
83
  arr.move(3, 0) // move "d" from index 3 to index 0
84
- expect(arr.values()).toEqual(["d", "a", "b", "c"])
84
+ expect(arr.values()).toEqual(['d', 'a', 'b', 'c'])
85
85
  unmount()
86
86
  })
87
87
 
88
- it("swap preserves all other items", () => {
89
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c", "d", "e"]))
88
+ it('swap preserves all other items', () => {
89
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c', 'd', 'e']))
90
90
 
91
91
  arr.swap(1, 3) // swap "b" and "d"
92
- expect(arr.values()).toEqual(["a", "d", "c", "b", "e"])
92
+ expect(arr.values()).toEqual(['a', 'd', 'c', 'b', 'e'])
93
93
  unmount()
94
94
  })
95
95
 
96
- it("prepend then remove first restores original", () => {
97
- const { result: arr, unmount } = mountWith(() => useFieldArray(["x", "y"]))
96
+ it('prepend then remove first restores original', () => {
97
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['x', 'y']))
98
98
 
99
- arr.prepend("new")
100
- expect(arr.values()).toEqual(["new", "x", "y"])
99
+ arr.prepend('new')
100
+ expect(arr.values()).toEqual(['new', 'x', 'y'])
101
101
  arr.remove(0)
102
- expect(arr.values()).toEqual(["x", "y"])
102
+ expect(arr.values()).toEqual(['x', 'y'])
103
103
  unmount()
104
104
  })
105
105
 
106
- it("insert at beginning is equivalent to prepend", () => {
107
- const { result: arr, unmount } = mountWith(() => useFieldArray(["b", "c"]))
106
+ it('insert at beginning is equivalent to prepend', () => {
107
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['b', 'c']))
108
108
 
109
- arr.insert(0, "a")
110
- expect(arr.values()).toEqual(["a", "b", "c"])
109
+ arr.insert(0, 'a')
110
+ expect(arr.values()).toEqual(['a', 'b', 'c'])
111
111
  unmount()
112
112
  })
113
113
 
114
- it("insert at end is equivalent to append", () => {
115
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b"]))
114
+ it('insert at end is equivalent to append', () => {
115
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b']))
116
116
 
117
- arr.insert(2, "c")
118
- expect(arr.values()).toEqual(["a", "b", "c"])
117
+ arr.insert(2, 'c')
118
+ expect(arr.values()).toEqual(['a', 'b', 'c'])
119
119
  unmount()
120
120
  })
121
121
 
122
- it("replace with empty array clears all items", () => {
123
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c"]))
122
+ it('replace with empty array clears all items', () => {
123
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c']))
124
124
 
125
125
  arr.replace([])
126
126
  expect(arr.values()).toEqual([])
@@ -128,11 +128,11 @@ describe("useFieldArray — additional operations", () => {
128
128
  unmount()
129
129
  })
130
130
 
131
- it("replace generates new keys for all items", () => {
132
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b"]))
131
+ it('replace generates new keys for all items', () => {
132
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b']))
133
133
 
134
134
  const keysBefore = arr.items().map((i: any) => i.key)
135
- arr.replace(["x", "y"])
135
+ arr.replace(['x', 'y'])
136
136
  const keysAfter = arr.items().map((i: any) => i.key)
137
137
 
138
138
  // All keys should be different since replace creates new items
@@ -141,7 +141,7 @@ describe("useFieldArray — additional operations", () => {
141
141
  unmount()
142
142
  })
143
143
 
144
- it("items signal is reactive — effect fires on append", () => {
144
+ it('items signal is reactive — effect fires on append', () => {
145
145
  const { result: arr, unmount } = mountWith(() => useFieldArray<string>([]))
146
146
 
147
147
  const lengths: number[] = []
@@ -151,34 +151,34 @@ describe("useFieldArray — additional operations", () => {
151
151
 
152
152
  expect(lengths).toEqual([0])
153
153
 
154
- arr.append("a")
154
+ arr.append('a')
155
155
  expect(lengths).toEqual([0, 1])
156
156
 
157
- arr.append("b")
157
+ arr.append('b')
158
158
  expect(lengths).toEqual([0, 1, 2])
159
159
 
160
160
  cleanup.dispose()
161
161
  unmount()
162
162
  })
163
163
 
164
- it("update preserves key identity", () => {
165
- const { result: arr, unmount } = mountWith(() => useFieldArray(["a", "b", "c"]))
164
+ it('update preserves key identity', () => {
165
+ const { result: arr, unmount } = mountWith(() => useFieldArray(['a', 'b', 'c']))
166
166
 
167
167
  const keyBefore = arr.items()[1]!.key
168
- arr.update(1, "updated")
168
+ arr.update(1, 'updated')
169
169
  const keyAfter = arr.items()[1]!.key
170
170
 
171
171
  // Same item, just value changed — key should be identical
172
172
  expect(keyAfter).toBe(keyBefore)
173
- expect(arr.items()[1]!.value()).toBe("updated")
173
+ expect(arr.items()[1]!.value()).toBe('updated')
174
174
  unmount()
175
175
  })
176
176
  })
177
177
 
178
178
  // ─── useWatch — reactivity ───────────────────────────────────────────────────
179
179
 
180
- describe("useWatch — reactivity", () => {
181
- it("single field watch is reactive to value changes", () => {
180
+ describe('useWatch — reactivity', () => {
181
+ it('single field watch is reactive to value changes', () => {
182
182
  const { result, unmount } = mountWith(() => {
183
183
  const form = useForm({
184
184
  initialValues: { count: 0 },
@@ -186,7 +186,7 @@ describe("useWatch — reactivity", () => {
186
186
  /* noop */
187
187
  },
188
188
  })
189
- const count = useWatch(form, "count")
189
+ const count = useWatch(form, 'count')
190
190
  return { form, count }
191
191
  })
192
192
 
@@ -207,10 +207,10 @@ describe("useWatch — reactivity", () => {
207
207
  unmount()
208
208
  })
209
209
 
210
- it("watch all fields is reactive to any field change", () => {
210
+ it('watch all fields is reactive to any field change', () => {
211
211
  const { result, unmount } = mountWith(() => {
212
212
  const form = useForm({
213
- initialValues: { first: "A", second: "B" },
213
+ initialValues: { first: 'A', second: 'B' },
214
214
  onSubmit: () => {
215
215
  /* noop */
216
216
  },
@@ -219,33 +219,33 @@ describe("useWatch — reactivity", () => {
219
219
  return { form, all }
220
220
  })
221
221
 
222
- expect(result.all()).toEqual({ first: "A", second: "B" })
222
+ expect(result.all()).toEqual({ first: 'A', second: 'B' })
223
223
 
224
- result.form.fields.first.setValue("X")
225
- expect(result.all()).toEqual({ first: "X", second: "B" })
224
+ result.form.fields.first.setValue('X')
225
+ expect(result.all()).toEqual({ first: 'X', second: 'B' })
226
226
 
227
- result.form.fields.second.setValue("Y")
228
- expect(result.all()).toEqual({ first: "X", second: "Y" })
227
+ result.form.fields.second.setValue('Y')
228
+ expect(result.all()).toEqual({ first: 'X', second: 'Y' })
229
229
  unmount()
230
230
  })
231
231
 
232
- it("multiple field watch returns signal array with correct types", () => {
232
+ it('multiple field watch returns signal array with correct types', () => {
233
233
  const { result, unmount } = mountWith(() => {
234
234
  const form = useForm({
235
- initialValues: { name: "Alice", age: 30 },
235
+ initialValues: { name: 'Alice', age: 30 },
236
236
  onSubmit: () => {
237
237
  /* noop */
238
238
  },
239
239
  })
240
- const [name, age] = useWatch(form, ["name", "age"])
240
+ const [name, age] = useWatch(form, ['name', 'age'])
241
241
  return { form, name, age }
242
242
  })
243
243
 
244
- expect(result.name!()).toBe("Alice")
244
+ expect(result.name!()).toBe('Alice')
245
245
  expect(result.age!()).toBe(30)
246
246
 
247
- result.form.fields.name.setValue("Bob")
248
- expect(result.name!()).toBe("Bob")
247
+ result.form.fields.name.setValue('Bob')
248
+ expect(result.name!()).toBe('Bob')
249
249
  expect(result.age!()).toBe(30) // unchanged
250
250
  unmount()
251
251
  })
@@ -253,11 +253,11 @@ describe("useWatch — reactivity", () => {
253
253
 
254
254
  // ─── useFormState — additional scenarios ─────────────────────────────────────
255
255
 
256
- describe("useFormState — additional scenarios", () => {
257
- it("tracks dirty fields correctly after multiple changes", () => {
256
+ describe('useFormState — additional scenarios', () => {
257
+ it('tracks dirty fields correctly after multiple changes', () => {
258
258
  const { result, unmount } = mountWith(() => {
259
259
  const form = useForm({
260
- initialValues: { email: "", name: "", age: 0 },
260
+ initialValues: { email: '', name: '', age: 0 },
261
261
  onSubmit: () => {
262
262
  /* noop */
263
263
  },
@@ -266,31 +266,31 @@ describe("useFormState — additional scenarios", () => {
266
266
  return { form, state }
267
267
  })
268
268
 
269
- result.form.fields.email.setValue("test@test.com")
270
- result.form.fields.name.setValue("Alice")
269
+ result.form.fields.email.setValue('test@test.com')
270
+ result.form.fields.name.setValue('Alice')
271
271
 
272
272
  const s = result.state()
273
273
  expect(s.dirtyFields).toEqual({ email: true, name: true })
274
274
  expect(s.isDirty).toBe(true)
275
275
 
276
276
  // Revert email
277
- result.form.fields.email.setValue("")
277
+ result.form.fields.email.setValue('')
278
278
  const s2 = result.state()
279
279
  expect(s2.dirtyFields).toEqual({ name: true })
280
280
  expect(s2.isDirty).toBe(true)
281
281
 
282
282
  // Revert name too
283
- result.form.fields.name.setValue("")
283
+ result.form.fields.name.setValue('')
284
284
  const s3 = result.state()
285
285
  expect(s3.dirtyFields).toEqual({})
286
286
  expect(s3.isDirty).toBe(false)
287
287
  unmount()
288
288
  })
289
289
 
290
- it("tracks touched fields after blur events", () => {
290
+ it('tracks touched fields after blur events', () => {
291
291
  const { result, unmount } = mountWith(() => {
292
292
  const form = useForm({
293
- initialValues: { email: "", password: "" },
293
+ initialValues: { email: '', password: '' },
294
294
  onSubmit: () => {
295
295
  /* noop */
296
296
  },
@@ -309,12 +309,12 @@ describe("useFormState — additional scenarios", () => {
309
309
  unmount()
310
310
  })
311
311
 
312
- it("submitCount and submitError are tracked", async () => {
312
+ it('submitCount and submitError are tracked', async () => {
313
313
  const { result, unmount } = mountWith(() => {
314
314
  const form = useForm({
315
- initialValues: { name: "valid" },
315
+ initialValues: { name: 'valid' },
316
316
  onSubmit: async () => {
317
- throw new Error("Submit failed")
317
+ throw new Error('Submit failed')
318
318
  },
319
319
  })
320
320
  const state = useFormState(form)
@@ -333,14 +333,14 @@ describe("useFormState — additional scenarios", () => {
333
333
  unmount()
334
334
  })
335
335
 
336
- it("isValidating is tracked during async validation", async () => {
336
+ it('isValidating is tracked during async validation', async () => {
337
337
  const { result, unmount } = mountWith(() => {
338
338
  const form = useForm({
339
- initialValues: { name: "" },
339
+ initialValues: { name: '' },
340
340
  validators: {
341
341
  name: async (v) => {
342
342
  await new Promise((r) => setTimeout(r, 20))
343
- return !v ? "Required" : undefined
343
+ return !v ? 'Required' : undefined
344
344
  },
345
345
  },
346
346
  onSubmit: () => {
@@ -364,17 +364,17 @@ describe("useFormState — additional scenarios", () => {
364
364
 
365
365
  // ─── Validation integration — schema-based ───────────────────────────────────
366
366
 
367
- describe("validation integration — schema-based", () => {
368
- it("schema errors are set only on fields without field-level errors", async () => {
367
+ describe('validation integration — schema-based', () => {
368
+ it('schema errors are set only on fields without field-level errors', async () => {
369
369
  const { result: form, unmount } = mountWith(() =>
370
370
  useForm({
371
- initialValues: { email: "", password: "" },
371
+ initialValues: { email: '', password: '' },
372
372
  validators: {
373
- email: (v) => (!v ? "Email required" : undefined),
373
+ email: (v) => (!v ? 'Email required' : undefined),
374
374
  },
375
375
  schema: (_values) => ({
376
- email: "Schema email error", // Should be overridden by field-level
377
- password: "Schema password error",
376
+ email: 'Schema email error', // Should be overridden by field-level
377
+ password: 'Schema password error',
378
378
  }),
379
379
  onSubmit: () => {
380
380
  /* noop */
@@ -385,19 +385,19 @@ describe("validation integration — schema-based", () => {
385
385
  await form.validate()
386
386
 
387
387
  // email has a field-level error ("Email required") — schema error ignored
388
- expect(form.fields.email.error()).toBe("Email required")
388
+ expect(form.fields.email.error()).toBe('Email required')
389
389
  // password has no field-level validator — schema error applied
390
- expect(form.fields.password.error()).toBe("Schema password error")
390
+ expect(form.fields.password.error()).toBe('Schema password error')
391
391
  unmount()
392
392
  })
393
393
 
394
- it("async schema validation works", async () => {
394
+ it('async schema validation works', async () => {
395
395
  const { result: form, unmount } = mountWith(() =>
396
396
  useForm({
397
- initialValues: { code: "" },
397
+ initialValues: { code: '' },
398
398
  schema: async (values) => {
399
399
  await new Promise((r) => setTimeout(r, 5))
400
- if (!values.code) return { code: "Code is required" }
400
+ if (!values.code) return { code: 'Code is required' }
401
401
  return {}
402
402
  },
403
403
  onSubmit: () => {
@@ -408,21 +408,21 @@ describe("validation integration — schema-based", () => {
408
408
 
409
409
  const valid = await form.validate()
410
410
  expect(valid).toBe(false)
411
- expect(form.fields.code.error()).toBe("Code is required")
411
+ expect(form.fields.code.error()).toBe('Code is required')
412
412
  unmount()
413
413
  })
414
414
  })
415
415
 
416
416
  // ─── form.reset() clears all field state ─────────────────────────────────────
417
417
 
418
- describe("form.reset() comprehensive", () => {
419
- it("clears all field state including errors, touched, dirty, submitCount, submitError", async () => {
418
+ describe('form.reset() comprehensive', () => {
419
+ it('clears all field state including errors, touched, dirty, submitCount, submitError', async () => {
420
420
  const { result: form, unmount } = mountWith(() =>
421
421
  useForm({
422
- initialValues: { email: "", password: "" },
422
+ initialValues: { email: '', password: '' },
423
423
  validators: {
424
- email: (v) => (!v ? "Required" : undefined),
425
- password: (v) => (!v ? "Required" : undefined),
424
+ email: (v) => (!v ? 'Required' : undefined),
425
+ password: (v) => (!v ? 'Required' : undefined),
426
426
  },
427
427
  onSubmit: () => {
428
428
  /* noop */
@@ -431,8 +431,8 @@ describe("form.reset() comprehensive", () => {
431
431
  )
432
432
 
433
433
  // Dirty up the form
434
- form.fields.email.setValue("changed")
435
- form.fields.password.setValue("changed")
434
+ form.fields.email.setValue('changed')
435
+ form.fields.password.setValue('changed')
436
436
  form.fields.email.setTouched()
437
437
  form.fields.password.setTouched()
438
438
  await form.handleSubmit() // triggers validation
@@ -448,8 +448,8 @@ describe("form.reset() comprehensive", () => {
448
448
  form.reset()
449
449
 
450
450
  // All state should be cleared
451
- expect(form.fields.email.value()).toBe("")
452
- expect(form.fields.password.value()).toBe("")
451
+ expect(form.fields.email.value()).toBe('')
452
+ expect(form.fields.password.value()).toBe('')
453
453
  expect(form.fields.email.error()).toBeUndefined()
454
454
  expect(form.fields.password.error()).toBeUndefined()
455
455
  expect(form.fields.email.touched()).toBe(false)
@@ -466,19 +466,19 @@ describe("form.reset() comprehensive", () => {
466
466
 
467
467
  // ─── Debounced validation — additional scenarios ─────────────────────────────
468
468
 
469
- describe("debounced validation — additional", () => {
470
- it("debounced validation on blur only fires after delay", async () => {
469
+ describe('debounced validation — additional', () => {
470
+ it('debounced validation on blur only fires after delay', async () => {
471
471
  const calls: string[] = []
472
472
  const { result: form, unmount } = mountWith(() =>
473
473
  useForm({
474
- initialValues: { query: "" },
474
+ initialValues: { query: '' },
475
475
  validators: {
476
476
  query: (v) => {
477
477
  calls.push(v as string)
478
478
  return undefined
479
479
  },
480
480
  },
481
- validateOn: "blur",
481
+ validateOn: 'blur',
482
482
  debounceMs: 40,
483
483
  onSubmit: () => {
484
484
  /* noop */
@@ -486,9 +486,9 @@ describe("debounced validation — additional", () => {
486
486
  }),
487
487
  )
488
488
 
489
- form.fields.query.setValue("a")
489
+ form.fields.query.setValue('a')
490
490
  form.fields.query.setTouched()
491
- form.fields.query.setValue("ab")
491
+ form.fields.query.setValue('ab')
492
492
  form.fields.query.setTouched()
493
493
 
494
494
  // Nothing fired yet
@@ -501,18 +501,18 @@ describe("debounced validation — additional", () => {
501
501
  unmount()
502
502
  })
503
503
 
504
- it("field-level reset clears debounce timer for that field", async () => {
504
+ it('field-level reset clears debounce timer for that field', async () => {
505
505
  let callCount = 0
506
506
  const { result: form, unmount } = mountWith(() =>
507
507
  useForm({
508
- initialValues: { name: "" },
508
+ initialValues: { name: '' },
509
509
  validators: {
510
510
  name: () => {
511
511
  callCount++
512
512
  return undefined
513
513
  },
514
514
  },
515
- validateOn: "blur",
515
+ validateOn: 'blur',
516
516
  debounceMs: 50,
517
517
  onSubmit: () => {
518
518
  /* noop */
@@ -533,10 +533,10 @@ describe("debounced validation — additional", () => {
533
533
 
534
534
  // ─── FormProvider with direct VNode children ─────────────────────────────────
535
535
 
536
- describe("FormProvider — VNode children branch", () => {
537
- it("renders when children is a direct VNode (not a function)", () => {
536
+ describe('FormProvider — VNode children branch', () => {
537
+ it('renders when children is a direct VNode (not a function)', () => {
538
538
  let contextForm: FormState<{ name: string }> | undefined
539
- const el = document.createElement("div")
539
+ const el = document.createElement('div')
540
540
  document.body.appendChild(el)
541
541
 
542
542
  function Child() {
@@ -546,7 +546,7 @@ describe("FormProvider — VNode children branch", () => {
546
546
 
547
547
  function TestComponent() {
548
548
  const form = useForm({
549
- initialValues: { name: "Direct" },
549
+ initialValues: { name: 'Direct' },
550
550
  onSubmit: () => {
551
551
  /* noop */
552
552
  },
@@ -560,7 +560,7 @@ describe("FormProvider — VNode children branch", () => {
560
560
 
561
561
  const unmount = mount(<TestComponent />, el)
562
562
  expect(contextForm).toBeDefined()
563
- expect(contextForm!.fields.name.value()).toBe("Direct")
563
+ expect(contextForm!.fields.name.value()).toBe('Direct')
564
564
  unmount()
565
565
  el.remove()
566
566
  })