tinybase 8.0.0-beta.3 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/@types/middleware/index.d.ts +44 -124
  2. package/@types/middleware/with-schemas/index.d.ts +44 -147
  3. package/@types/ui-react-dom/index.d.ts +6 -4
  4. package/@types/ui-react-dom/with-schemas/index.d.ts +6 -4
  5. package/index.js +100 -69
  6. package/mergeable-store/index.js +99 -48
  7. package/mergeable-store/with-schemas/index.js +99 -48
  8. package/middleware/index.js +1 -39
  9. package/middleware/with-schemas/index.js +1 -39
  10. package/min/index.js +1 -1
  11. package/min/index.js.gz +0 -0
  12. package/min/mergeable-store/index.js +1 -1
  13. package/min/mergeable-store/index.js.gz +0 -0
  14. package/min/mergeable-store/with-schemas/index.js +1 -1
  15. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  16. package/min/middleware/index.js +1 -1
  17. package/min/middleware/index.js.gz +0 -0
  18. package/min/middleware/with-schemas/index.js +1 -1
  19. package/min/middleware/with-schemas/index.js.gz +0 -0
  20. package/min/omni/index.js +1 -1
  21. package/min/omni/index.js.gz +0 -0
  22. package/min/omni/with-schemas/index.js +1 -1
  23. package/min/omni/with-schemas/index.js.gz +0 -0
  24. package/min/store/index.js +1 -1
  25. package/min/store/index.js.gz +0 -0
  26. package/min/store/with-schemas/index.js +1 -1
  27. package/min/store/with-schemas/index.js.gz +0 -0
  28. package/min/ui-react-dom/index.js +1 -1
  29. package/min/ui-react-dom/index.js.gz +0 -0
  30. package/min/ui-react-dom/with-schemas/index.js +1 -1
  31. package/min/ui-react-dom/with-schemas/index.js.gz +0 -0
  32. package/min/ui-react-inspector/index.js +1 -1
  33. package/min/ui-react-inspector/index.js.gz +0 -0
  34. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  35. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  36. package/min/with-schemas/index.js +1 -1
  37. package/min/with-schemas/index.js.gz +0 -0
  38. package/omni/index.js +156 -102
  39. package/omni/with-schemas/index.js +156 -102
  40. package/package.json +6 -6
  41. package/readme.md +3 -3
  42. package/releases.md +39 -4
  43. package/store/index.js +99 -48
  44. package/store/with-schemas/index.js +99 -48
  45. package/ui-react-dom/index.js +56 -34
  46. package/ui-react-dom/with-schemas/index.js +56 -34
  47. package/ui-react-inspector/index.js +155 -82
  48. package/ui-react-inspector/with-schemas/index.js +155 -82
  49. package/with-schemas/index.js +100 -69
@@ -85,7 +85,6 @@ const isObject = (obj) =>
85
85
  const objIds = object.keys;
86
86
  const objFreeze = object.freeze;
87
87
  const objNew = (entries = []) => object.fromEntries(entries);
88
- const objMerge = (...objs) => object.assign({}, ...objs);
89
88
  const objHas = (obj, id) => id in obj;
90
89
  const objDel = (obj, id) => {
91
90
  delete obj[id];
@@ -631,10 +630,24 @@ const createStore = () => {
631
630
  );
632
631
  const setOrDelTables = (tables) =>
633
632
  objIsEmpty(tables) ? delTables() : setTables(tables);
634
- const setOrDelCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
633
+ const setOrDelCell = (
634
+ tableId,
635
+ rowId,
636
+ cellId,
637
+ cell,
638
+ skipMiddleware,
639
+ skipRowMiddleware,
640
+ ) =>
635
641
  isUndefined(cell)
636
642
  ? delCell(tableId, rowId, cellId, true, skipMiddleware)
637
- : setCell(tableId, rowId, cellId, cell, skipMiddleware);
643
+ : setCell(
644
+ tableId,
645
+ rowId,
646
+ cellId,
647
+ cell,
648
+ skipMiddleware,
649
+ skipRowMiddleware,
650
+ );
638
651
  const setOrDelValues = (values) =>
639
652
  objIsEmpty(values) ? delValues() : setValues(values);
640
653
  const setOrDelValue = (valueId, value, skipMiddleware) =>
@@ -734,6 +747,30 @@ const createStore = () => {
734
747
  ),
735
748
  objIsEqual,
736
749
  );
750
+ const applyRowDirectly = (tableId, tableMap, rowId, row, skipMiddleware) => {
751
+ mapMatch(
752
+ mapEnsure(tableMap, rowId, () => {
753
+ rowIdsChanged(tableId, rowId, 1);
754
+ return mapNew();
755
+ }),
756
+ row,
757
+ (rowMap, cellId, cell) =>
758
+ ifNotUndefined(
759
+ getValidatedCell(tableId, rowId, cellId, cell),
760
+ (validCell) =>
761
+ setValidCell(
762
+ tableId,
763
+ rowId,
764
+ rowMap,
765
+ cellId,
766
+ validCell,
767
+ skipMiddleware,
768
+ ),
769
+ ),
770
+ (rowMap, cellId) =>
771
+ delValidCell(tableId, tableMap, rowId, rowMap, cellId, true),
772
+ );
773
+ };
737
774
  const setValidCell = (tableId, rowId, rowMap, cellId, cell, skipMiddleware) =>
738
775
  ifTransformed(
739
776
  cell,
@@ -1410,7 +1447,14 @@ const createStore = () => {
1410
1447
  tableId,
1411
1448
  rowId,
1412
1449
  );
1413
- const setCell = (tableId, rowId, cellId, cell, skipMiddleware) =>
1450
+ const setCell = (
1451
+ tableId,
1452
+ rowId,
1453
+ cellId,
1454
+ cell,
1455
+ skipMiddleware,
1456
+ skipRowMiddleware,
1457
+ ) =>
1414
1458
  fluentTransaction(
1415
1459
  (tableId2, rowId2, cellId2) =>
1416
1460
  ifNotUndefined(
@@ -1420,15 +1464,47 @@ const createStore = () => {
1420
1464
  cellId2,
1421
1465
  isFunction(cell) ? cell(getCell(tableId2, rowId2, cellId2)) : cell,
1422
1466
  ),
1423
- (validCell) =>
1424
- setCellIntoNewRow(
1425
- tableId2,
1426
- getOrCreateTable(tableId2),
1427
- rowId2,
1428
- cellId2,
1429
- validCell,
1430
- skipMiddleware,
1431
- ),
1467
+ (validCell) => {
1468
+ const tableMap = getOrCreateTable(tableId2);
1469
+ ifNotUndefined(
1470
+ skipMiddleware || skipRowMiddleware || !middleware[14]?.()
1471
+ ? void 0
1472
+ : middleware[3],
1473
+ (willSetRow) => {
1474
+ const existingRowMap = mapGet(tableMap, rowId2);
1475
+ const prospectiveRow = {
1476
+ ...(existingRowMap ? mapToObj(existingRowMap) : {}),
1477
+ [cellId2]: validCell,
1478
+ };
1479
+ ifNotUndefined(
1480
+ whileMutating(() =>
1481
+ willSetRow(
1482
+ tableId2,
1483
+ rowId2,
1484
+ structuredClone(prospectiveRow),
1485
+ ),
1486
+ ),
1487
+ (row) =>
1488
+ applyRowDirectly(
1489
+ tableId2,
1490
+ tableMap,
1491
+ rowId2,
1492
+ row,
1493
+ skipMiddleware,
1494
+ ),
1495
+ );
1496
+ },
1497
+ () =>
1498
+ setCellIntoNewRow(
1499
+ tableId2,
1500
+ tableMap,
1501
+ rowId2,
1502
+ cellId2,
1503
+ validCell,
1504
+ skipMiddleware,
1505
+ ),
1506
+ );
1507
+ },
1432
1508
  ),
1433
1509
  tableId,
1434
1510
  rowId,
@@ -1477,7 +1553,14 @@ const createStore = () => {
1477
1553
  isUndefined(row)
1478
1554
  ? delRow(tableId, rowId)
1479
1555
  : objMap(row, (cell, cellId) =>
1480
- setOrDelCell(tableId, rowId, cellId, cell),
1556
+ setOrDelCell(
1557
+ tableId,
1558
+ rowId,
1559
+ cellId,
1560
+ cell,
1561
+ void 0,
1562
+ true,
1563
+ ),
1481
1564
  ),
1482
1565
  ),
1483
1566
  );
@@ -1640,37 +1723,6 @@ const createStore = () => {
1640
1723
  mapToObj3(changedCellIds),
1641
1724
  mapToObj(changedValueIds),
1642
1725
  ];
1643
- const doDidSetRows = () => {
1644
- if (middleware[14]) {
1645
- const changedCells2 = clonedChangedCells(changedCells);
1646
- collForEach(changedCells2, (rows, tableId) =>
1647
- collForEach(rows, (cells, rowId) => {
1648
- if (
1649
- !arrayEvery(
1650
- collValues(cells),
1651
- ([oldCell, newCell]) => oldCell === newCell,
1652
- )
1653
- ) {
1654
- const newRow = getRow(tableId, rowId);
1655
- const oldRow = objMerge(newRow);
1656
- collForEach(cells, ([oldCell], cellId) =>
1657
- isUndefined(oldCell)
1658
- ? objDel(oldRow, cellId)
1659
- : (oldRow[cellId] = oldCell),
1660
- );
1661
- const didSetRow = middleware[14](tableId, rowId, oldRow, newRow);
1662
- if (!objIsEqual(didSetRow, newRow)) {
1663
- const setOrDelRow = objMap(newRow, () => void 0);
1664
- objMap(didSetRow, (cell, cellId) => (setOrDelRow[cellId] = cell));
1665
- objMap(setOrDelRow, (cell, cellId) =>
1666
- setOrDelCell(tableId, rowId, cellId, cell, true),
1667
- );
1668
- }
1669
- }
1670
- }),
1671
- );
1672
- }
1673
- };
1674
1726
  const finishTransaction = (doRollback) => {
1675
1727
  if (transactions > 0) {
1676
1728
  transactions--;
@@ -1680,7 +1732,6 @@ const createStore = () => {
1680
1732
  callInvalidCellListeners(1);
1681
1733
  if (!collIsEmpty(changedCells)) {
1682
1734
  callTabularListenersForChanges(1);
1683
- doDidSetRows();
1684
1735
  }
1685
1736
  callInvalidValueListeners(1);
1686
1737
  if (!collIsEmpty(changedValues)) {
@@ -1851,7 +1902,7 @@ const createStore = () => {
1851
1902
  willDelValues,
1852
1903
  willDelValue,
1853
1904
  willApplyChanges,
1854
- didSetRow,
1905
+ hasWillSetRowCallbacks,
1855
1906
  ) =>
1856
1907
  (middleware = [
1857
1908
  willSetContent,
@@ -1868,7 +1919,7 @@ const createStore = () => {
1868
1919
  willDelValues,
1869
1920
  willDelValue,
1870
1921
  willApplyChanges,
1871
- didSetRow,
1922
+ hasWillSetRowCallbacks,
1872
1923
  ]);
1873
1924
  const setInternalListeners = (
1874
1925
  preStartTransaction,
@@ -58,6 +58,14 @@ const isArray = (thing) => Array.isArray(thing);
58
58
  const size = (arrayOrString) => arrayOrString.length;
59
59
  const getUndefined = () => void 0;
60
60
  const getArg = (value) => value;
61
+ const tryReturn = (tryF, catchReturn) => {
62
+ try {
63
+ return tryF();
64
+ } catch {
65
+ /* istanbul ignore next */
66
+ return catchReturn;
67
+ }
68
+ };
61
69
 
62
70
  const arrayEvery = (array, cb) => array.every(cb);
63
71
  const arrayIsEqual = (array1, array2) =>
@@ -678,15 +686,17 @@ const EditableThing = ({
678
686
  const [stringThing, setStringThing] = useState();
679
687
  const [numberThing, setNumberThing] = useState();
680
688
  const [booleanThing, setBooleanThing] = useState();
681
- const [objectThingJson, setObjectThingJson] = useState(EMPTY_STRING);
682
- const [arrayThingJson, setArrayThingJson] = useState(EMPTY_STRING);
689
+ const [objectThing, setObjectThing] = useState('{}');
690
+ const [arrayThing, setArrayThing] = useState('[]');
691
+ const [objectClassName, setObjectClassName] = useState('');
692
+ const [arrayClassName, setArrayClassName] = useState('');
683
693
  if (currentThing !== thing) {
684
694
  setThingType(getCellOrValueType(thing));
685
695
  setCurrentThing(thing);
686
696
  if (isObject(thing)) {
687
- setObjectThingJson(jsonString(thing));
697
+ setObjectThing(jsonString(thing));
688
698
  } else if (isArray(thing)) {
689
- setArrayThingJson(jsonString(thing));
699
+ setArrayThing(jsonString(thing));
690
700
  } else {
691
701
  setStringThing(String(thing));
692
702
  setNumberThing(Number(thing) || 0);
@@ -701,6 +711,22 @@ const EditableThing = ({
701
711
  },
702
712
  [onThingChange],
703
713
  );
714
+ const handleJsonThingChange = useCallback(
715
+ (value, setTypedThing, isThing, setTypedClassName) => {
716
+ setTypedThing(value);
717
+ try {
718
+ const object = jsonParse(value);
719
+ if (isThing(object)) {
720
+ setCurrentThing(object);
721
+ onThingChange(object);
722
+ setTypedClassName('');
723
+ }
724
+ } catch {
725
+ setTypedClassName('invalid');
726
+ }
727
+ },
728
+ [onThingChange],
729
+ );
704
730
  const handleTypeChange = useCallback(() => {
705
731
  if (!hasSchema?.()) {
706
732
  const nextType = getTypeCase(
@@ -716,8 +742,8 @@ const EditableThing = ({
716
742
  stringThing,
717
743
  numberThing,
718
744
  booleanThing,
719
- objectThingJson ? jsonParse(objectThingJson) : {},
720
- arrayThingJson ? jsonParse(arrayThingJson) : [],
745
+ tryReturn(() => jsonParse(objectThing), {}),
746
+ tryReturn(() => jsonParse(arrayThing), []),
721
747
  );
722
748
  setThingType(nextType);
723
749
  setCurrentThing(thing2);
@@ -729,8 +755,8 @@ const EditableThing = ({
729
755
  stringThing,
730
756
  numberThing,
731
757
  booleanThing,
732
- objectThingJson,
733
- arrayThingJson,
758
+ objectThing,
759
+ arrayThing,
734
760
  thingType,
735
761
  ]);
736
762
  const widget = getTypeCase(
@@ -783,41 +809,37 @@ const EditableThing = ({
783
809
  thingType,
784
810
  ),
785
811
  /* @__PURE__ */ jsx(
786
- 'textarea',
812
+ 'input',
787
813
  {
788
- value: objectThingJson,
814
+ value: objectThing,
815
+ className: objectClassName,
789
816
  onChange: useCallback(
790
- (event) => {
791
- const str = event[CURRENT_TARGET][_VALUE];
792
- setObjectThingJson(str);
793
- try {
794
- const parsed = jsonParse(str);
795
- if (isObject(parsed)) {
796
- onThingChange(parsed);
797
- }
798
- } catch {}
799
- },
800
- [onThingChange],
817
+ (event) =>
818
+ handleJsonThingChange(
819
+ event[CURRENT_TARGET][_VALUE],
820
+ setObjectThing,
821
+ isObject,
822
+ setObjectClassName,
823
+ ),
824
+ [handleJsonThingChange],
801
825
  ),
802
826
  },
803
827
  thingType,
804
828
  ),
805
829
  /* @__PURE__ */ jsx(
806
- 'textarea',
830
+ 'input',
807
831
  {
808
- value: arrayThingJson,
832
+ value: arrayThing,
833
+ className: arrayClassName,
809
834
  onChange: useCallback(
810
- (event) => {
811
- const str = event[CURRENT_TARGET][_VALUE];
812
- setArrayThingJson(str);
813
- try {
814
- const parsed = jsonParse(str);
815
- if (isArray(parsed)) {
816
- onThingChange(parsed);
817
- }
818
- } catch {}
819
- },
820
- [onThingChange],
835
+ (event) =>
836
+ handleJsonThingChange(
837
+ event[CURRENT_TARGET][_VALUE],
838
+ setArrayThing,
839
+ isArray,
840
+ setArrayClassName,
841
+ ),
842
+ [handleJsonThingChange],
821
843
  ),
822
844
  },
823
845
  thingType,
@@ -58,6 +58,14 @@ const isArray = (thing) => Array.isArray(thing);
58
58
  const size = (arrayOrString) => arrayOrString.length;
59
59
  const getUndefined = () => void 0;
60
60
  const getArg = (value) => value;
61
+ const tryReturn = (tryF, catchReturn) => {
62
+ try {
63
+ return tryF();
64
+ } catch {
65
+ /* istanbul ignore next */
66
+ return catchReturn;
67
+ }
68
+ };
61
69
 
62
70
  const arrayEvery = (array, cb) => array.every(cb);
63
71
  const arrayIsEqual = (array1, array2) =>
@@ -678,15 +686,17 @@ const EditableThing = ({
678
686
  const [stringThing, setStringThing] = useState();
679
687
  const [numberThing, setNumberThing] = useState();
680
688
  const [booleanThing, setBooleanThing] = useState();
681
- const [objectThingJson, setObjectThingJson] = useState(EMPTY_STRING);
682
- const [arrayThingJson, setArrayThingJson] = useState(EMPTY_STRING);
689
+ const [objectThing, setObjectThing] = useState('{}');
690
+ const [arrayThing, setArrayThing] = useState('[]');
691
+ const [objectClassName, setObjectClassName] = useState('');
692
+ const [arrayClassName, setArrayClassName] = useState('');
683
693
  if (currentThing !== thing) {
684
694
  setThingType(getCellOrValueType(thing));
685
695
  setCurrentThing(thing);
686
696
  if (isObject(thing)) {
687
- setObjectThingJson(jsonString(thing));
697
+ setObjectThing(jsonString(thing));
688
698
  } else if (isArray(thing)) {
689
- setArrayThingJson(jsonString(thing));
699
+ setArrayThing(jsonString(thing));
690
700
  } else {
691
701
  setStringThing(String(thing));
692
702
  setNumberThing(Number(thing) || 0);
@@ -701,6 +711,22 @@ const EditableThing = ({
701
711
  },
702
712
  [onThingChange],
703
713
  );
714
+ const handleJsonThingChange = useCallback(
715
+ (value, setTypedThing, isThing, setTypedClassName) => {
716
+ setTypedThing(value);
717
+ try {
718
+ const object = jsonParse(value);
719
+ if (isThing(object)) {
720
+ setCurrentThing(object);
721
+ onThingChange(object);
722
+ setTypedClassName('');
723
+ }
724
+ } catch {
725
+ setTypedClassName('invalid');
726
+ }
727
+ },
728
+ [onThingChange],
729
+ );
704
730
  const handleTypeChange = useCallback(() => {
705
731
  if (!hasSchema?.()) {
706
732
  const nextType = getTypeCase(
@@ -716,8 +742,8 @@ const EditableThing = ({
716
742
  stringThing,
717
743
  numberThing,
718
744
  booleanThing,
719
- objectThingJson ? jsonParse(objectThingJson) : {},
720
- arrayThingJson ? jsonParse(arrayThingJson) : [],
745
+ tryReturn(() => jsonParse(objectThing), {}),
746
+ tryReturn(() => jsonParse(arrayThing), []),
721
747
  );
722
748
  setThingType(nextType);
723
749
  setCurrentThing(thing2);
@@ -729,8 +755,8 @@ const EditableThing = ({
729
755
  stringThing,
730
756
  numberThing,
731
757
  booleanThing,
732
- objectThingJson,
733
- arrayThingJson,
758
+ objectThing,
759
+ arrayThing,
734
760
  thingType,
735
761
  ]);
736
762
  const widget = getTypeCase(
@@ -783,41 +809,37 @@ const EditableThing = ({
783
809
  thingType,
784
810
  ),
785
811
  /* @__PURE__ */ jsx(
786
- 'textarea',
812
+ 'input',
787
813
  {
788
- value: objectThingJson,
814
+ value: objectThing,
815
+ className: objectClassName,
789
816
  onChange: useCallback(
790
- (event) => {
791
- const str = event[CURRENT_TARGET][_VALUE];
792
- setObjectThingJson(str);
793
- try {
794
- const parsed = jsonParse(str);
795
- if (isObject(parsed)) {
796
- onThingChange(parsed);
797
- }
798
- } catch {}
799
- },
800
- [onThingChange],
817
+ (event) =>
818
+ handleJsonThingChange(
819
+ event[CURRENT_TARGET][_VALUE],
820
+ setObjectThing,
821
+ isObject,
822
+ setObjectClassName,
823
+ ),
824
+ [handleJsonThingChange],
801
825
  ),
802
826
  },
803
827
  thingType,
804
828
  ),
805
829
  /* @__PURE__ */ jsx(
806
- 'textarea',
830
+ 'input',
807
831
  {
808
- value: arrayThingJson,
832
+ value: arrayThing,
833
+ className: arrayClassName,
809
834
  onChange: useCallback(
810
- (event) => {
811
- const str = event[CURRENT_TARGET][_VALUE];
812
- setArrayThingJson(str);
813
- try {
814
- const parsed = jsonParse(str);
815
- if (isArray(parsed)) {
816
- onThingChange(parsed);
817
- }
818
- } catch {}
819
- },
820
- [onThingChange],
835
+ (event) =>
836
+ handleJsonThingChange(
837
+ event[CURRENT_TARGET][_VALUE],
838
+ setArrayThing,
839
+ isArray,
840
+ setArrayClassName,
841
+ ),
842
+ [handleJsonThingChange],
821
843
  ),
822
844
  },
823
845
  thingType,