react-store-input 0.1.4 → 0.1.6

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/index.d.mts CHANGED
@@ -2,10 +2,9 @@ export { Store, StoreSubscriber, useStore } from './use_store.mjs';
2
2
  export { useSelector } from './use_selector.mjs';
3
3
  export { useSubscribe } from './use_subscribe.mjs';
4
4
  export { StoreControllerProps, useStoreController } from './use_store_controller.mjs';
5
- export { useStoreInputWithName } from './use_store_input_with_name.mjs';
5
+ export { InferNameFromProps, StoreInputWithNameProps, useStoreInputWithName } from './use_store_input_with_name.mjs';
6
6
  export { StoreInputProps, useStoreInput } from './use_store_input.mjs';
7
- export { Input, Select, StoreComponentProps, StoreComponentPropsWithStore, Textarea, useStoreComponent } from './use_store_component.mjs';
7
+ export { Input, Select, StoreComponentPropsWithStore, Textarea, useStoreComponent } from './use_store_component.mjs';
8
8
  export { FormStore, useFormStore } from './use_form_store.mjs';
9
- export { deserialize, serialize } from './serialize.mjs';
10
9
  import 'react';
11
10
  import './create_render.mjs';
package/dist/index.d.ts CHANGED
@@ -2,10 +2,9 @@ export { Store, StoreSubscriber, useStore } from './use_store.js';
2
2
  export { useSelector } from './use_selector.js';
3
3
  export { useSubscribe } from './use_subscribe.js';
4
4
  export { StoreControllerProps, useStoreController } from './use_store_controller.js';
5
- export { useStoreInputWithName } from './use_store_input_with_name.js';
5
+ export { InferNameFromProps, StoreInputWithNameProps, useStoreInputWithName } from './use_store_input_with_name.js';
6
6
  export { StoreInputProps, useStoreInput } from './use_store_input.js';
7
- export { Input, Select, StoreComponentProps, StoreComponentPropsWithStore, Textarea, useStoreComponent } from './use_store_component.js';
7
+ export { Input, Select, StoreComponentPropsWithStore, Textarea, useStoreComponent } from './use_store_component.js';
8
8
  export { FormStore, useFormStore } from './use_form_store.js';
9
- export { deserialize, serialize } from './serialize.js';
10
9
  import 'react';
11
10
  import './create_render.js';
package/dist/index.js CHANGED
@@ -33,8 +33,6 @@ __export(index_exports, {
33
33
  Input: () => Input,
34
34
  Select: () => Select,
35
35
  Textarea: () => Textarea,
36
- deserialize: () => deserialize,
37
- serialize: () => serialize,
38
36
  useFormStore: () => useFormStore,
39
37
  useSelector: () => useSelector,
40
38
  useStore: () => useStore,
@@ -121,18 +119,8 @@ function useSelector(store, selector, compare = (a, b) => a === b) {
121
119
  var import_react4 = require("react");
122
120
  function useStoreController(store, props) {
123
121
  const ref = (0, import_react4.useRef)(null);
122
+ (0, import_react4.useImperativeHandle)(props.ref, () => ref.current, []);
124
123
  const dispatchKey = (0, import_react4.useId)();
125
- (0, import_react4.useEffect)(() => {
126
- const element = ref.current;
127
- if (!element) {
128
- return;
129
- }
130
- if (typeof props.ref === "function") {
131
- props.ref(element);
132
- } else if (props.ref) {
133
- props.ref.current = element;
134
- }
135
- }, []);
136
124
  useSubscribe(store, (state, key) => {
137
125
  if (key === dispatchKey) {
138
126
  return;
@@ -140,7 +128,7 @@ function useStoreController(store, props) {
140
128
  if (!ref.current) return;
141
129
  props.onSubscribe(state, ref.current);
142
130
  });
143
- const onChange = () => {
131
+ const dispatch = () => {
144
132
  store.dispatch(
145
133
  (state) => {
146
134
  const element = ref.current;
@@ -154,7 +142,7 @@ function useStoreController(store, props) {
154
142
  };
155
143
  return {
156
144
  ref,
157
- onChange
145
+ dispatch
158
146
  };
159
147
  }
160
148
 
@@ -162,20 +150,18 @@ function useStoreController(store, props) {
162
150
  var import_react5 = require("react");
163
151
  var import_date_fns = require("date-fns");
164
152
  function useStoreInput(store, props) {
165
- const toInputValue = (value) => {
153
+ const toInputValue = props.toInputValue || ((value) => {
166
154
  if (value === void 0 || value === null) {
167
155
  return "";
168
156
  }
169
157
  if (props.type === "datetime-local") {
170
- if (value instanceof Date) {
171
- return (0, import_date_fns.format)(value, "yyyy-MM-dd'T'HH:mm:ss");
172
- }
173
- if (typeof value === "string") {
174
- return toInputValue(new Date(value));
158
+ const date = new Date(value);
159
+ if (!isNaN(date.getTime())) {
160
+ return (0, import_date_fns.format)(date, "yyyy-MM-dd'T'HH:mm:ss");
175
161
  }
176
162
  }
177
163
  return String(value);
178
- };
164
+ });
179
165
  const getDefaultValue = () => {
180
166
  if (props.defaultValue !== void 0) {
181
167
  return props.defaultValue;
@@ -200,16 +186,15 @@ function useStoreInput(store, props) {
200
186
  }
201
187
  return toInputChecked(props.getter(store.state));
202
188
  };
203
- function toStateValue(value) {
204
- const selected = props.getter(store.state);
205
- if (typeof selected === "number") {
189
+ const toStateValue = props.toStateValue || ((value) => {
190
+ if (props.type === "number" || props.type === "range") {
206
191
  return Number(value);
207
192
  }
208
- if (selected instanceof Date) {
193
+ if (props.type === "datetime-local") {
209
194
  return new Date(value);
210
195
  }
211
196
  return value;
212
- }
197
+ });
213
198
  const inputProps = useStoreController(store, {
214
199
  ref: props.ref,
215
200
  onSubscribe: (state, element) => {
@@ -242,7 +227,7 @@ function useStoreInput(store, props) {
242
227
  defaultValue: getDefaultValue(),
243
228
  defaultChecked: getDefaultChecked(),
244
229
  onChange: (event) => {
245
- inputProps.onChange();
230
+ inputProps.dispatch();
246
231
  props.onChange?.(event);
247
232
  }
248
233
  };
@@ -276,15 +261,24 @@ function useStoreInputWithName(store, props) {
276
261
  var import_react6 = require("react");
277
262
  var import_react7 = __toESM(require("react"));
278
263
  function useStoreComponent(store) {
279
- const input = (0, import_react6.useCallback)(function Component(props) {
280
- return /* @__PURE__ */ import_react7.default.createElement(Input, { store, ...props });
281
- }, []);
282
- const select = (0, import_react6.useCallback)(function Component(props) {
283
- return /* @__PURE__ */ import_react7.default.createElement(Select, { store, ...props });
284
- }, []);
285
- const textarea = (0, import_react6.useCallback)(function Component(props) {
286
- return /* @__PURE__ */ import_react7.default.createElement(Textarea, { store, ...props });
287
- }, []);
264
+ const input = (0, import_react6.useCallback)(
265
+ function Component(props) {
266
+ return /* @__PURE__ */ import_react7.default.createElement(Input, { store, ...props });
267
+ },
268
+ []
269
+ );
270
+ const select = (0, import_react6.useCallback)(
271
+ function Component(props) {
272
+ return /* @__PURE__ */ import_react7.default.createElement(Select, { store, ...props });
273
+ },
274
+ []
275
+ );
276
+ const textarea = (0, import_react6.useCallback)(
277
+ function Component(props) {
278
+ return /* @__PURE__ */ import_react7.default.createElement(Textarea, { store, ...props });
279
+ },
280
+ []
281
+ );
288
282
  return {
289
283
  input,
290
284
  select,
@@ -295,27 +289,51 @@ function Input({
295
289
  store,
296
290
  getter,
297
291
  setter,
292
+ toInputValue,
293
+ toStateValue,
298
294
  ...props
299
295
  }) {
300
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
296
+ const storeProps = useStoreInputWithName(store, {
297
+ ...props,
298
+ getter,
299
+ setter,
300
+ toInputValue,
301
+ toStateValue
302
+ });
301
303
  return /* @__PURE__ */ import_react7.default.createElement("input", { ...props, ...storeProps });
302
304
  }
303
305
  function Select({
304
306
  store,
305
307
  getter,
306
308
  setter,
309
+ toInputValue,
310
+ toStateValue,
307
311
  ...props
308
312
  }) {
309
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
313
+ const storeProps = useStoreInputWithName(store, {
314
+ ...props,
315
+ getter,
316
+ setter,
317
+ toInputValue,
318
+ toStateValue
319
+ });
310
320
  return /* @__PURE__ */ import_react7.default.createElement("select", { ...props, ...storeProps });
311
321
  }
312
322
  function Textarea({
313
323
  store,
314
324
  getter,
315
325
  setter,
326
+ toInputValue,
327
+ toStateValue,
316
328
  ...props
317
329
  }) {
318
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
330
+ const storeProps = useStoreInputWithName(store, {
331
+ ...props,
332
+ getter,
333
+ setter,
334
+ toInputValue,
335
+ toStateValue
336
+ });
319
337
  return /* @__PURE__ */ import_react7.default.createElement("textarea", { ...props, ...storeProps });
320
338
  }
321
339
 
@@ -346,100 +364,11 @@ function useFormStore(initialState) {
346
364
  ...storeComponent
347
365
  };
348
366
  }
349
-
350
- // src/serialize.ts
351
- function serialize(value) {
352
- if (value === void 0) {
353
- return void 0;
354
- }
355
- if (value === null) {
356
- return {
357
- type: "null",
358
- value: null
359
- };
360
- }
361
- if (typeof value === "string") {
362
- return {
363
- type: "string",
364
- value
365
- };
366
- }
367
- if (typeof value === "number") {
368
- return {
369
- type: "number",
370
- value
371
- };
372
- }
373
- if (typeof value === "boolean") {
374
- return {
375
- type: "boolean",
376
- value
377
- };
378
- }
379
- if (value instanceof Date) {
380
- return {
381
- type: "date",
382
- value: value.toISOString()
383
- };
384
- }
385
- if (Array.isArray(value)) {
386
- return {
387
- type: "array",
388
- value: value.map((item) => serialize(item))
389
- };
390
- }
391
- if (typeof value === "object") {
392
- return {
393
- type: "object",
394
- value: Object.entries(value).reduce((acc, [key, value2]) => {
395
- return {
396
- ...acc,
397
- [key]: serialize(value2)
398
- };
399
- }, {})
400
- };
401
- }
402
- return void 0;
403
- }
404
- function deserialize(data) {
405
- if (data === void 0) {
406
- return void 0;
407
- }
408
- if (typeof data === "object" && data !== null && "type" in data && "value" in data) {
409
- const { type, value } = data;
410
- switch (type) {
411
- case "null":
412
- return null;
413
- case "string":
414
- return value;
415
- case "number":
416
- return value;
417
- case "boolean":
418
- return value;
419
- case "date":
420
- return new Date(value);
421
- case "array":
422
- return value.map((item) => deserialize(item));
423
- case "object":
424
- return Object.entries(value).reduce((acc, [key, value2]) => {
425
- return {
426
- ...acc,
427
- [key]: deserialize(value2)
428
- };
429
- }, {});
430
- default:
431
- return void 0;
432
- }
433
- }
434
- return void 0;
435
- }
436
367
  // Annotate the CommonJS export names for ESM import in node:
437
368
  0 && (module.exports = {
438
369
  Input,
439
370
  Select,
440
371
  Textarea,
441
- deserialize,
442
- serialize,
443
372
  useFormStore,
444
373
  useSelector,
445
374
  useStore,
package/dist/index.mjs CHANGED
@@ -70,21 +70,11 @@ function useSelector(store, selector, compare = (a, b) => a === b) {
70
70
  }
71
71
 
72
72
  // src/use_store_controller.tsx
73
- import { useEffect as useEffect2, useId, useRef as useRef2 } from "react";
73
+ import { useId, useImperativeHandle, useRef as useRef2 } from "react";
74
74
  function useStoreController(store, props) {
75
75
  const ref = useRef2(null);
76
+ useImperativeHandle(props.ref, () => ref.current, []);
76
77
  const dispatchKey = useId();
77
- useEffect2(() => {
78
- const element = ref.current;
79
- if (!element) {
80
- return;
81
- }
82
- if (typeof props.ref === "function") {
83
- props.ref(element);
84
- } else if (props.ref) {
85
- props.ref.current = element;
86
- }
87
- }, []);
88
78
  useSubscribe(store, (state, key) => {
89
79
  if (key === dispatchKey) {
90
80
  return;
@@ -92,7 +82,7 @@ function useStoreController(store, props) {
92
82
  if (!ref.current) return;
93
83
  props.onSubscribe(state, ref.current);
94
84
  });
95
- const onChange = () => {
85
+ const dispatch = () => {
96
86
  store.dispatch(
97
87
  (state) => {
98
88
  const element = ref.current;
@@ -106,7 +96,7 @@ function useStoreController(store, props) {
106
96
  };
107
97
  return {
108
98
  ref,
109
- onChange
99
+ dispatch
110
100
  };
111
101
  }
112
102
 
@@ -114,20 +104,18 @@ function useStoreController(store, props) {
114
104
  import "react";
115
105
  import { format } from "date-fns";
116
106
  function useStoreInput(store, props) {
117
- const toInputValue = (value) => {
107
+ const toInputValue = props.toInputValue || ((value) => {
118
108
  if (value === void 0 || value === null) {
119
109
  return "";
120
110
  }
121
111
  if (props.type === "datetime-local") {
122
- if (value instanceof Date) {
123
- return format(value, "yyyy-MM-dd'T'HH:mm:ss");
124
- }
125
- if (typeof value === "string") {
126
- return toInputValue(new Date(value));
112
+ const date = new Date(value);
113
+ if (!isNaN(date.getTime())) {
114
+ return format(date, "yyyy-MM-dd'T'HH:mm:ss");
127
115
  }
128
116
  }
129
117
  return String(value);
130
- };
118
+ });
131
119
  const getDefaultValue = () => {
132
120
  if (props.defaultValue !== void 0) {
133
121
  return props.defaultValue;
@@ -152,16 +140,15 @@ function useStoreInput(store, props) {
152
140
  }
153
141
  return toInputChecked(props.getter(store.state));
154
142
  };
155
- function toStateValue(value) {
156
- const selected = props.getter(store.state);
157
- if (typeof selected === "number") {
143
+ const toStateValue = props.toStateValue || ((value) => {
144
+ if (props.type === "number" || props.type === "range") {
158
145
  return Number(value);
159
146
  }
160
- if (selected instanceof Date) {
147
+ if (props.type === "datetime-local") {
161
148
  return new Date(value);
162
149
  }
163
150
  return value;
164
- }
151
+ });
165
152
  const inputProps = useStoreController(store, {
166
153
  ref: props.ref,
167
154
  onSubscribe: (state, element) => {
@@ -194,7 +181,7 @@ function useStoreInput(store, props) {
194
181
  defaultValue: getDefaultValue(),
195
182
  defaultChecked: getDefaultChecked(),
196
183
  onChange: (event) => {
197
- inputProps.onChange();
184
+ inputProps.dispatch();
198
185
  props.onChange?.(event);
199
186
  }
200
187
  };
@@ -225,20 +212,27 @@ function useStoreInputWithName(store, props) {
225
212
  }
226
213
 
227
214
  // src/use_store_component.tsx
228
- import {
229
- useCallback
230
- } from "react";
215
+ import { useCallback } from "react";
231
216
  import React from "react";
232
217
  function useStoreComponent(store) {
233
- const input = useCallback(function Component(props) {
234
- return /* @__PURE__ */ React.createElement(Input, { store, ...props });
235
- }, []);
236
- const select = useCallback(function Component(props) {
237
- return /* @__PURE__ */ React.createElement(Select, { store, ...props });
238
- }, []);
239
- const textarea = useCallback(function Component(props) {
240
- return /* @__PURE__ */ React.createElement(Textarea, { store, ...props });
241
- }, []);
218
+ const input = useCallback(
219
+ function Component(props) {
220
+ return /* @__PURE__ */ React.createElement(Input, { store, ...props });
221
+ },
222
+ []
223
+ );
224
+ const select = useCallback(
225
+ function Component(props) {
226
+ return /* @__PURE__ */ React.createElement(Select, { store, ...props });
227
+ },
228
+ []
229
+ );
230
+ const textarea = useCallback(
231
+ function Component(props) {
232
+ return /* @__PURE__ */ React.createElement(Textarea, { store, ...props });
233
+ },
234
+ []
235
+ );
242
236
  return {
243
237
  input,
244
238
  select,
@@ -249,27 +243,51 @@ function Input({
249
243
  store,
250
244
  getter,
251
245
  setter,
246
+ toInputValue,
247
+ toStateValue,
252
248
  ...props
253
249
  }) {
254
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
250
+ const storeProps = useStoreInputWithName(store, {
251
+ ...props,
252
+ getter,
253
+ setter,
254
+ toInputValue,
255
+ toStateValue
256
+ });
255
257
  return /* @__PURE__ */ React.createElement("input", { ...props, ...storeProps });
256
258
  }
257
259
  function Select({
258
260
  store,
259
261
  getter,
260
262
  setter,
263
+ toInputValue,
264
+ toStateValue,
261
265
  ...props
262
266
  }) {
263
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
267
+ const storeProps = useStoreInputWithName(store, {
268
+ ...props,
269
+ getter,
270
+ setter,
271
+ toInputValue,
272
+ toStateValue
273
+ });
264
274
  return /* @__PURE__ */ React.createElement("select", { ...props, ...storeProps });
265
275
  }
266
276
  function Textarea({
267
277
  store,
268
278
  getter,
269
279
  setter,
280
+ toInputValue,
281
+ toStateValue,
270
282
  ...props
271
283
  }) {
272
- const storeProps = useStoreInputWithName(store, { ...props, getter, setter });
284
+ const storeProps = useStoreInputWithName(store, {
285
+ ...props,
286
+ getter,
287
+ setter,
288
+ toInputValue,
289
+ toStateValue
290
+ });
273
291
  return /* @__PURE__ */ React.createElement("textarea", { ...props, ...storeProps });
274
292
  }
275
293
 
@@ -300,99 +318,10 @@ function useFormStore(initialState) {
300
318
  ...storeComponent
301
319
  };
302
320
  }
303
-
304
- // src/serialize.ts
305
- function serialize(value) {
306
- if (value === void 0) {
307
- return void 0;
308
- }
309
- if (value === null) {
310
- return {
311
- type: "null",
312
- value: null
313
- };
314
- }
315
- if (typeof value === "string") {
316
- return {
317
- type: "string",
318
- value
319
- };
320
- }
321
- if (typeof value === "number") {
322
- return {
323
- type: "number",
324
- value
325
- };
326
- }
327
- if (typeof value === "boolean") {
328
- return {
329
- type: "boolean",
330
- value
331
- };
332
- }
333
- if (value instanceof Date) {
334
- return {
335
- type: "date",
336
- value: value.toISOString()
337
- };
338
- }
339
- if (Array.isArray(value)) {
340
- return {
341
- type: "array",
342
- value: value.map((item) => serialize(item))
343
- };
344
- }
345
- if (typeof value === "object") {
346
- return {
347
- type: "object",
348
- value: Object.entries(value).reduce((acc, [key, value2]) => {
349
- return {
350
- ...acc,
351
- [key]: serialize(value2)
352
- };
353
- }, {})
354
- };
355
- }
356
- return void 0;
357
- }
358
- function deserialize(data) {
359
- if (data === void 0) {
360
- return void 0;
361
- }
362
- if (typeof data === "object" && data !== null && "type" in data && "value" in data) {
363
- const { type, value } = data;
364
- switch (type) {
365
- case "null":
366
- return null;
367
- case "string":
368
- return value;
369
- case "number":
370
- return value;
371
- case "boolean":
372
- return value;
373
- case "date":
374
- return new Date(value);
375
- case "array":
376
- return value.map((item) => deserialize(item));
377
- case "object":
378
- return Object.entries(value).reduce((acc, [key, value2]) => {
379
- return {
380
- ...acc,
381
- [key]: deserialize(value2)
382
- };
383
- }, {});
384
- default:
385
- return void 0;
386
- }
387
- }
388
- return void 0;
389
- }
390
321
  export {
391
322
  Input,
392
323
  Select,
393
324
  Textarea,
394
- deserialize,
395
- serialize,
396
325
  useFormStore,
397
326
  useSelector,
398
327
  useStore,
@@ -2,6 +2,8 @@ import { CreateRender } from './create_render.mjs';
2
2
  import { Store } from './use_store.mjs';
3
3
  import { useStoreComponent } from './use_store_component.mjs';
4
4
  import 'react';
5
+ import './use_store_input_with_name.mjs';
6
+ import './use_store_input.mjs';
5
7
 
6
8
  type FormStore<TState> = Store<TState> & ReturnType<typeof useStoreComponent<TState>> & {
7
9
  render: CreateRender<TState>;
@@ -2,6 +2,8 @@ import { CreateRender } from './create_render.js';
2
2
  import { Store } from './use_store.js';
3
3
  import { useStoreComponent } from './use_store_component.js';
4
4
  import 'react';
5
+ import './use_store_input_with_name.js';
6
+ import './use_store_input.js';
5
7
 
6
8
  type FormStore<TState> = Store<TState> & ReturnType<typeof useStoreComponent<TState>> & {
7
9
  render: CreateRender<TState>;