@resistdesign/voltra 3.0.0-alpha.25 → 3.0.0-alpha.27

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/README.md CHANGED
@@ -218,6 +218,14 @@ How it works:
218
218
  - Strategy is auto-selected:
219
219
  - DOM + History API => browser history strategy.
220
220
  - Otherwise => in-memory native strategy.
221
+ - Native strategy automatically wires Android hardware back to route history.
222
+ - If Voltra can go back (`history.index > 0`), it consumes the event and navigates back.
223
+ - If Voltra cannot go back, the event is not consumed so OS/native container behavior continues.
224
+
225
+ Optional back affordances:
226
+
227
+ - `adapter.back?.()` navigates backward when supported.
228
+ - `adapter.canGoBack?.()` reports whether back navigation is currently possible.
221
229
 
222
230
  Escape hatches (root-only):
223
231
 
@@ -1,4 +1,4 @@
1
- import type { AuthInfo, CORSPatter, RouteAuthConfig, RouteMap } from "../Router/Types";
1
+ import type { AuthInfo, CORSPattern, RouteAuthConfig, RouteMap } from "../Router/Types";
2
2
  import type { DataItemDBDriver, DataItemDBDriverConfig, ItemRelationshipDBDriver } from "../ORM/drivers/common/Types";
3
3
  import type { TypeInfoDataItem, TypeInfoMap } from "../../common/TypeParsing/TypeInfo";
4
4
  import type { TypeInfoORMDACConfig, TypeInfoORMIndexingConfig } from "../ORM/TypeInfoORMService";
@@ -53,7 +53,7 @@ export type DBXRuntimeConfig = {
53
53
  /**
54
54
  * Allowed origins used to generate CORS headers.
55
55
  */
56
- allowedOrigins?: CORSPatter[];
56
+ allowedOrigins?: CORSPattern[];
57
57
  /**
58
58
  * Optional DAC configuration (excluding accessing role).
59
59
  */
@@ -86,7 +86,7 @@ export type DBXRuntime = {
86
86
  /**
87
87
  * Allowed origins for CORS headers.
88
88
  */
89
- allowedOrigins: CORSPatter[];
89
+ allowedOrigins: CORSPattern[];
90
90
  /**
91
91
  * Driver resolver for item types.
92
92
  */
@@ -28,7 +28,7 @@ export * from "./exact/ExactDdb";
28
28
  export * from "./exact/ExactIndex";
29
29
  export * from "./exact/ExactS3";
30
30
  export * from "./fulltext/FullTextMemoryBackend";
31
- export { FullTextDdbBackend, FullTextDdbWriter, type BatchGetItemInput, type BatchGetItemOutput, type BatchWriteItemInput, type BatchWriteItemOutput, type FullTextTableNames, type GetItemInput, type GetItemOutput, type KeysAndAttributes, type QueryInput, type QueryOutput, } from "./fulltext/FullTextDdbBackend";
31
+ export { FullTextDdbBackend, FullTextDdbWriter, type FullTextTableNames, } from "./fulltext/FullTextDdbBackend";
32
32
  export * from "./fulltext/Schema";
33
33
  export * from "./lossy/LossyDdb";
34
34
  export * from "./lossy/LossyIndex";
@@ -1,2 +1,12 @@
1
1
  export * from "./Types";
2
2
  export * from "./SupportedTypeInfoORMDBDrivers";
3
+ /**
4
+ * @category api
5
+ * @group Type Dependencies
6
+ */
7
+ export type { ListItemsConfig, ListItemsResults, } from "../../../../common/SearchTypes";
8
+ /**
9
+ * @category api
10
+ * @group Type Dependencies
11
+ */
12
+ export type { TypeInfoDataItem, TypeInfoPack, } from "../../../../common/TypeParsing/TypeInfo";
@@ -5,3 +5,18 @@ export * from "./InMemoryItemRelationshipDBDriver";
5
5
  export * from "./InMemoryFileItemDBDriver";
6
6
  export * from "./IndexingRelationshipDriver";
7
7
  export * from "./common";
8
+ /**
9
+ * @category api
10
+ * @group Type Dependencies
11
+ */
12
+ export type { ListRelationshipsConfig, SearchCriteria, } from "../../../common/SearchTypes";
13
+ /**
14
+ * @category api
15
+ * @group Type Dependencies
16
+ */
17
+ export type { TypeInfoMap, } from "../../../common/TypeParsing/TypeInfo";
18
+ /**
19
+ * @category api
20
+ * @group Type Dependencies
21
+ */
22
+ export type { S3SpecificConfig, } from "./S3FileItemDBDriver/ConfigTypes";
@@ -5,3 +5,29 @@ export * from "./drivers";
5
5
  export * from "./TypeInfoORMService";
6
6
  export * from "./DACUtils";
7
7
  export * from "./ORMRouteMap";
8
+ /**
9
+ * @category api
10
+ * @group Type Dependencies
11
+ */
12
+ export type { DeleteRelationshipResults, ORMOperation, RelationshipOperation, TypeInfoORMAPI, TypeInfoORMContext, } from "../../common/TypeInfoORM/Types";
13
+ /**
14
+ * @category api
15
+ * @group Type Dependencies
16
+ */
17
+ export type { LiteralValue, TypeInfo, TypeInfoField, TypeOperation, } from "../../common/TypeParsing/TypeInfo";
18
+ /**
19
+ * @category api
20
+ * @group Type Dependencies
21
+ */
22
+ export type { CustomTypeInfoFieldValidatorMap, TypeInfoValidationResults, } from "../../common/TypeParsing/Validation";
23
+ /**
24
+ * @category api
25
+ * @group Type Dependencies
26
+ */
27
+ export type { BaseDACRole, DACAccessResult, DACConstraint, DACDataItemResourceAccessResultMap, DACRole, } from "../DataAccessControl";
28
+ export { DACConstraintType } from "../DataAccessControl";
29
+ /**
30
+ * @category api
31
+ * @group Type Dependencies
32
+ */
33
+ export type { AuthInfo, NormalizedCloudFunctionEventData, Route, RouteAuthConfig, RouteHandler, RouteMap, } from "../Router/Types";
@@ -1,4 +1,4 @@
1
- import { CORSPatter } from "./Types";
1
+ import { CORSPattern } from "./Types";
2
2
  /**
3
3
  * Check origin equality against an allowed string.
4
4
  * @returns True when the origin exactly matches the string.
@@ -37,7 +37,7 @@ origin?: string,
37
37
  /**
38
38
  * Allowed origin matcher (string equality or regex test).
39
39
  */
40
- corsPattern?: CORSPatter) => boolean;
40
+ corsPattern?: CORSPattern) => boolean;
41
41
  /**
42
42
  * Resolve the origin if it is allowed by the CORS patterns.
43
43
  * @returns The origin if allowed, otherwise an empty string.
@@ -50,7 +50,7 @@ origin?: string,
50
50
  /**
51
51
  * Allowed origin matchers to check.
52
52
  */
53
- corsPatterns?: CORSPatter[]) => string;
53
+ corsPatterns?: CORSPattern[]) => string;
54
54
  /**
55
55
  * Build CORS response headers for a given origin and allow list.
56
56
  * @returns CORS headers for the response.
@@ -63,4 +63,4 @@ origin?: string,
63
63
  /**
64
64
  * Allowed origin matchers to check.
65
65
  */
66
- corsPatterns?: CORSPatter[]) => Record<string, string>;
66
+ corsPatterns?: CORSPattern[]) => Record<string, string>;
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * A pattern for a CORS origin.
3
3
  * */
4
- export type CORSPatter = string | RegExp;
4
+ export type CORSPattern = string | RegExp;
5
+ export type CORSPatter = CORSPattern;
5
6
  /**
6
7
  * User authentication information.
7
8
  * Typically, from Cognito.
@@ -134,4 +135,4 @@ export type CloudFunctionEventTransformer = (event: any) => NormalizedCloudFunct
134
135
  * @param debug When true, log handler inputs and outputs.
135
136
  * @returns Cloud function response object.
136
137
  */
137
- export type CloudFunctionEventRouter = (event: any, eventTransformer: CloudFunctionEventTransformer, routeMap: RouteMap, allowedOrigins: CORSPatter[], errorShouldBeExposedToClient?: (error: unknown) => boolean, debug?: boolean) => Promise<CloudFunctionResponse>;
138
+ export type CloudFunctionEventRouter = (event: any, eventTransformer: CloudFunctionEventTransformer, routeMap: RouteMap, allowedOrigins: CORSPattern[], errorShouldBeExposedToClient?: (error: unknown) => boolean, debug?: boolean) => Promise<CloudFunctionResponse>;
@@ -9,3 +9,8 @@ export * from "./resolveSuite";
9
9
  export * from "./createAutoField";
10
10
  export * from "./createFormRenderer";
11
11
  export * from "./mergeSuites";
12
+ /**
13
+ * @category app
14
+ * @group Type Dependencies
15
+ */
16
+ export type { LiteralValue, TypeInfoDataItem, TypeInfoField, } from "../../../common/TypeParsing/TypeInfo";
@@ -66,7 +66,7 @@ export type CustomTypeActionPayload = {
66
66
  /**
67
67
  * Context passed to field renderers.
68
68
  */
69
- export type FieldRenderContext = {
69
+ export type FieldRenderContext<RenderOutput = unknown> = {
70
70
  /** Type info describing the field to render. */
71
71
  field: TypeInfoField;
72
72
  /** Key that identifies the field in the form values. */
@@ -97,11 +97,22 @@ export type FieldRenderContext = {
97
97
  onRelationAction?: (payload: RelationActionPayload) => void;
98
98
  /** Optional callback for custom type actions. */
99
99
  onCustomTypeAction?: (payload: CustomTypeActionPayload) => void;
100
+ /** Render any field with the same dispatch rules as the parent AutoField call. */
101
+ renderField: (input: {
102
+ field: TypeInfoField;
103
+ fieldKey: string;
104
+ value: FieldValue | undefined;
105
+ onChange: (value: FieldValue) => void;
106
+ error?: string;
107
+ disabled?: boolean;
108
+ onRelationAction?: (payload: RelationActionPayload) => void;
109
+ onCustomTypeAction?: (payload: CustomTypeActionPayload) => void;
110
+ }) => RenderOutput;
100
111
  };
101
112
  /**
102
113
  * Renderer function for a single field kind.
103
114
  */
104
- export type FieldRenderer<RenderOutput = unknown> = (context: FieldRenderContext) => RenderOutput;
115
+ export type FieldRenderer<RenderOutput = unknown> = (context: FieldRenderContext<RenderOutput>) => RenderOutput;
105
116
  /**
106
117
  * Optional primitive component contract for suites.
107
118
  */
@@ -8,3 +8,8 @@ export type { ComponentSuite, FieldKind, FieldRenderContext, FieldRenderer, Fiel
8
8
  export { createAutoField, createFormRenderer, getFieldKind, mergeSuites, resolveSuite, withRendererOverride, } from "./core";
9
9
  export * from "./Engine";
10
10
  export * from "./UI";
11
+ /**
12
+ * @category app
13
+ * @group Type Dependencies
14
+ */
15
+ export type { LiteralValue, TypeInfo, TypeInfoDataItem, TypeInfoField, TypeOperation, } from "../../common/TypeParsing/TypeInfo";
package/app/index.js CHANGED
@@ -603,6 +603,20 @@ var computeTrackPixels = ({
603
603
  };
604
604
 
605
605
  // src/app/utils/History.ts
606
+ var createHistoryBackHandler = (history) => {
607
+ return {
608
+ /**
609
+ * @returns True when back navigation was handled by history.
610
+ */
611
+ handle: () => {
612
+ if (history.index > 0) {
613
+ history.back();
614
+ return true;
615
+ }
616
+ return false;
617
+ }
618
+ };
619
+ };
606
620
  var ensurePrefix = (value, prefix) => value ? value.startsWith(prefix) ? value : `${prefix}${value}` : "";
607
621
  var parseHistoryPath = (inputPath) => {
608
622
  const raw = String(inputPath ?? "").trim();
@@ -756,7 +770,9 @@ var createRouteAdapterFromHistory = (history) => {
756
770
  },
757
771
  replace: (path) => {
758
772
  history.replace(path, { replaceSearch: true });
759
- }
773
+ },
774
+ back: history.back,
775
+ canGoBack: () => history.index > 0
760
776
  };
761
777
  };
762
778
 
@@ -770,6 +786,37 @@ var getWindow = () => {
770
786
  }
771
787
  return void 0;
772
788
  };
789
+ var getRuntimeRequire = () => {
790
+ const runtimeRequire = globalThis.__voltra_require__;
791
+ if (typeof runtimeRequire === "function") {
792
+ return runtimeRequire;
793
+ }
794
+ try {
795
+ return (0, eval)("require");
796
+ } catch (error) {
797
+ return void 0;
798
+ }
799
+ };
800
+ var tryGetReactNativeBackHandler = () => {
801
+ const runtimeRequire = getRuntimeRequire();
802
+ if (!runtimeRequire) {
803
+ return void 0;
804
+ }
805
+ try {
806
+ const reactNativeModule = runtimeRequire("react-native");
807
+ const platform = reactNativeModule?.Platform;
808
+ const backHandler = reactNativeModule?.BackHandler;
809
+ if (platform?.OS !== "android") {
810
+ return void 0;
811
+ }
812
+ if (typeof backHandler?.addEventListener !== "function") {
813
+ return void 0;
814
+ }
815
+ return backHandler;
816
+ } catch (error) {
817
+ return void 0;
818
+ }
819
+ };
773
820
  var canUseBrowserHistory = () => {
774
821
  const WINDOW = getWindow();
775
822
  return Boolean(
@@ -823,7 +870,9 @@ var createBrowserRouteAdapter = () => {
823
870
  }
824
871
  WINDOW.history.replaceState({}, title, path);
825
872
  notify();
826
- }
873
+ },
874
+ back: () => WINDOW?.history?.back(),
875
+ canGoBack: () => (WINDOW?.history?.length ?? 0) > 1
827
876
  };
828
877
  };
829
878
  var createNativeRouteAdapter = (initialPath = "/", ingress) => {
@@ -832,7 +881,8 @@ var createNativeRouteAdapter = (initialPath = "/", ingress) => {
832
881
  const history = createMemoryHistory(initialPath);
833
882
  const adapter = createRouteAdapterFromHistory(history);
834
883
  let stopIngress;
835
- let started = false;
884
+ let stopBackHandler;
885
+ let ingressStarted = false;
836
886
  let subscribers = 0;
837
887
  const applyPath = (path, mode) => {
838
888
  const normalizedPath = parseHistoryPath(path).path;
@@ -846,10 +896,10 @@ var createNativeRouteAdapter = (initialPath = "/", ingress) => {
846
896
  history.replace(normalizedPath, { replaceSearch: true });
847
897
  };
848
898
  const startIngress = async () => {
849
- if (started || !ingress) {
899
+ if (ingressStarted || !ingress) {
850
900
  return;
851
901
  }
852
- started = true;
902
+ ingressStarted = true;
853
903
  const startKey = history.location.key;
854
904
  const startIndex = history.index;
855
905
  if (ingress.subscribe) {
@@ -870,6 +920,31 @@ var createNativeRouteAdapter = (initialPath = "/", ingress) => {
870
920
  }
871
921
  }
872
922
  };
923
+ const startBackHandler = () => {
924
+ if (stopBackHandler) {
925
+ return;
926
+ }
927
+ const reactNativeBackHandler = tryGetReactNativeBackHandler();
928
+ if (!reactNativeBackHandler) {
929
+ return;
930
+ }
931
+ const historyBackHandler = createHistoryBackHandler(history);
932
+ const handleHardwareBackPress = () => historyBackHandler.handle();
933
+ const subscription = reactNativeBackHandler.addEventListener(
934
+ "hardwareBackPress",
935
+ handleHardwareBackPress
936
+ );
937
+ stopBackHandler = () => {
938
+ if (typeof subscription?.remove === "function") {
939
+ subscription.remove();
940
+ return;
941
+ }
942
+ reactNativeBackHandler.removeEventListener?.(
943
+ "hardwareBackPress",
944
+ handleHardwareBackPress
945
+ );
946
+ };
947
+ };
873
948
  return {
874
949
  ...adapter,
875
950
  push: (path, title) => {
@@ -888,18 +963,23 @@ var createNativeRouteAdapter = (initialPath = "/", ingress) => {
888
963
  subscribers += 1;
889
964
  if (subscribers === 1) {
890
965
  void startIngress();
966
+ startBackHandler();
891
967
  }
892
968
  const unlisten = adapter.subscribe(listener);
893
969
  return () => {
894
970
  unlisten();
895
971
  subscribers = Math.max(0, subscribers - 1);
896
- if (subscribers === 0 && stopIngress) {
897
- stopIngress();
972
+ if (subscribers === 0) {
973
+ stopIngress?.();
898
974
  stopIngress = void 0;
899
- started = false;
975
+ ingressStarted = false;
976
+ stopBackHandler?.();
977
+ stopBackHandler = void 0;
900
978
  }
901
979
  };
902
- }
980
+ },
981
+ back: adapter.back,
982
+ canGoBack: adapter.canGoBack
903
983
  };
904
984
  };
905
985
  var createUniversalAdapter = (options = {}) => {
@@ -1473,7 +1553,7 @@ var resolveSuite = (overrides, fallback) => {
1473
1553
 
1474
1554
  // src/app/forms/core/createAutoField.ts
1475
1555
  var createAutoField = (suite) => {
1476
- return (props) => {
1556
+ const renderField = (props) => {
1477
1557
  const { field, fieldKey, value, onChange, error, disabled } = props;
1478
1558
  const { tags } = field;
1479
1559
  const context = {
@@ -1491,11 +1571,13 @@ var createAutoField = (suite) => {
1491
1571
  allowCustomSelection: tags?.allowCustomSelection,
1492
1572
  customType: tags?.customType,
1493
1573
  onRelationAction: props.onRelationAction,
1494
- onCustomTypeAction: props.onCustomTypeAction
1574
+ onCustomTypeAction: props.onCustomTypeAction,
1575
+ renderField
1495
1576
  };
1496
1577
  const kind = getFieldKind(field);
1497
1578
  return suite.renderers[kind](context);
1498
1579
  };
1580
+ return renderField;
1499
1581
  };
1500
1582
 
1501
1583
  // src/app/forms/core/createFormRenderer.ts
@@ -1733,4 +1815,4 @@ var AutoForm = ({
1733
1815
  );
1734
1816
  };
1735
1817
 
1736
- export { ApplicationStateContext, ApplicationStateProvider, AutoForm, AutoFormView, Route, RouteContext, RouteContextConsumer, RouteContextProvider, RouteProvider, TypeInfoORMClient, buildHistoryPath, buildQueryString, buildRoutePath, canUseBrowserHistory, computeAreaBounds, computeTrackPixels, createAutoField, createBrowserRouteAdapter, createEasyLayout, createFormRenderer, createManualRouteAdapter, createMemoryHistory, createNativeRouteAdapter, createRouteAdapterFromHistory, createUniversalAdapter, getApplicationStateIdentifier, getApplicationStateModified, getApplicationStateValue, getApplicationStateValueStructure, getChangedDependencyIndexes, getEasyLayoutTemplateDetails, getFieldKind, getFullUrl, getPascalCaseAreaName, handleRequest, mergeSuites, parseHistoryPath, parseTemplate, requestHandlerFactory, resolveSuite, sendServiceRequest, setApplicationStateModified, setApplicationStateValue, useApplicationStateLoader, useApplicationStateValue, useApplicationStateValueStructure, useController, useDebugDependencies, useFormEngine, useRouteContext, useTypeInfoORMAPI, validateAreas, withRendererOverride };
1818
+ export { ApplicationStateContext, ApplicationStateProvider, AutoForm, AutoFormView, Route, RouteContext, RouteContextConsumer, RouteContextProvider, RouteProvider, TypeInfoORMClient, buildHistoryPath, buildQueryString, buildRoutePath, canUseBrowserHistory, computeAreaBounds, computeTrackPixels, createAutoField, createBrowserRouteAdapter, createEasyLayout, createFormRenderer, createHistoryBackHandler, createManualRouteAdapter, createMemoryHistory, createNativeRouteAdapter, createRouteAdapterFromHistory, createUniversalAdapter, getApplicationStateIdentifier, getApplicationStateModified, getApplicationStateValue, getApplicationStateValueStructure, getChangedDependencyIndexes, getEasyLayoutTemplateDetails, getFieldKind, getFullUrl, getPascalCaseAreaName, handleRequest, mergeSuites, parseHistoryPath, parseTemplate, requestHandlerFactory, resolveSuite, sendServiceRequest, setApplicationStateModified, setApplicationStateValue, tryGetReactNativeBackHandler, useApplicationStateLoader, useApplicationStateValue, useApplicationStateValueStructure, useController, useDebugDependencies, useFormEngine, useRouteContext, useTypeInfoORMAPI, validateAreas, withRendererOverride };
@@ -98,6 +98,23 @@ export type HistoryController = {
98
98
  */
99
99
  listen: (listener: HistoryListener) => () => void;
100
100
  };
101
+ /**
102
+ * Back-navigation consumption helper for shared history controllers.
103
+ *
104
+ * Returns `true` only when history consumed the back action.
105
+ *
106
+ * Example:
107
+ * ```ts
108
+ * const handler = createHistoryBackHandler(history);
109
+ * const consumed = handler.handle();
110
+ * ```
111
+ */
112
+ export declare const createHistoryBackHandler: (history: HistoryController) => {
113
+ /**
114
+ * @returns True when back navigation was handled by history.
115
+ */
116
+ handle: () => boolean;
117
+ };
101
118
  /**
102
119
  * Parse a path-like value into normalized path/search/hash parts.
103
120
  *
@@ -18,6 +18,10 @@ export type RouteAdapter = {
18
18
  push?: (path: string, title?: string) => void;
19
19
  /** Optional navigation helper for adapters that can replace state. */
20
20
  replace?: (path: string, title?: string) => void;
21
+ /** Optional navigation helper for adapters that can go backward. */
22
+ back?: () => void;
23
+ /** Optional capability check for backward navigation. */
24
+ canGoBack?: () => boolean;
21
25
  };
22
26
  /**
23
27
  * Supported query value types for route serialization.
@@ -55,6 +55,16 @@ export type UniversalRouteIngress = {
55
55
  */
56
56
  mapURLToPath?: (url: string) => string;
57
57
  };
58
+ type ReactNativeBackHandler = {
59
+ addEventListener: (eventName: "hardwareBackPress", listener: () => boolean) => {
60
+ remove?: () => void;
61
+ } | void;
62
+ removeEventListener?: (eventName: "hardwareBackPress", listener: () => boolean) => void;
63
+ };
64
+ /**
65
+ * Safely resolve React Native BackHandler for Android runtimes only.
66
+ */
67
+ export declare const tryGetReactNativeBackHandler: () => ReactNativeBackHandler | undefined;
58
68
  /**
59
69
  * Detect whether browser history is available at runtime.
60
70
  */
@@ -71,3 +81,4 @@ export declare const createNativeRouteAdapter: (initialPath?: string, ingress?:
71
81
  * Create a runtime-selected RouteAdapter for web/native environments.
72
82
  */
73
83
  export declare const createUniversalAdapter: (options?: CreateUniversalAdapterOptions) => RouteAdapter;
84
+ export {};
@@ -22,3 +22,18 @@ export * from "./UniversalRouteAdapter";
22
22
  export * from "./Service";
23
23
  export * from "./TypeInfoORMAPIUtils";
24
24
  export * from "./TypeInfoORMClient";
25
+ /**
26
+ * @category app
27
+ * @group Type Dependencies
28
+ */
29
+ export type { ListItemsConfig, ListItemsResults, ListRelationshipsConfig, } from "../../common/SearchTypes";
30
+ /**
31
+ * @category app
32
+ * @group Type Dependencies
33
+ */
34
+ export type { DeleteRelationshipResults, TypeInfoORMAPIRoutePaths, TypeInfoORMClientAPI, TypeInfoORMServiceError, } from "../../common/TypeInfoORM/Types";
35
+ /**
36
+ * @category app
37
+ * @group Type Dependencies
38
+ */
39
+ export type { TypeInfoDataItem, } from "../../common/TypeParsing/TypeInfo";
@@ -1 +1,6 @@
1
1
  export * from "./ItemRelationshipValidation";
2
+ /**
3
+ * @category common
4
+ * @group Type Dependencies
5
+ */
6
+ export type { TypeInfoValidationResults, } from "../TypeParsing/Validation";
@@ -12,7 +12,7 @@ import { TypeInfoDataItem, TypeOperation } from "../TypeParsing/TypeInfo";
12
12
  * */
13
13
  export declare const ITEM_RELATIONSHIP_DAC_RESOURCE_NAME = "TYPE_INFO_ORM_ITEM_RELATIONSHIP";
14
14
  /**
15
- * A set of possible operations for a {@link ItemRelationshipInfo}.
15
+ * A set of possible operations for an item relationship record.
16
16
  * */
17
17
  export declare enum RelationshipOperation {
18
18
  /**
@@ -1 +1,11 @@
1
1
  export * from "./Types";
2
+ /**
3
+ * @category common
4
+ * @group Type Dependencies
5
+ */
6
+ export type { ListItemsConfig, ListItemsResults, ListRelationshipsConfig, } from "../SearchTypes";
7
+ /**
8
+ * @category common
9
+ * @group Type Dependencies
10
+ */
11
+ export type { TypeInfoDataItem, TypeOperation, } from "../TypeParsing/TypeInfo";
package/native/index.js CHANGED
@@ -4,35 +4,6 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  // src/native/forms/suite.ts
6
6
 
7
- // src/app/forms/core/getFieldKind.ts
8
- var hasSelectableValues = (field) => {
9
- const possibleValues = field.possibleValues ?? [];
10
- return possibleValues.some(
11
- (value) => typeof value === "string" || typeof value === "number"
12
- );
13
- };
14
- var getFieldKind = (field) => {
15
- if (field.typeReference) {
16
- return field.array ? "relation_array" : "relation_single";
17
- }
18
- if (field.tags?.customType) {
19
- return field.array ? "custom_array" : "custom_single";
20
- }
21
- if (field.array) {
22
- return "array";
23
- }
24
- if (hasSelectableValues(field)) {
25
- return "enum_select";
26
- }
27
- if (field.type === "boolean") {
28
- return "boolean";
29
- }
30
- if (field.type === "number") {
31
- return "number";
32
- }
33
- return "string";
34
- };
35
-
36
7
  // src/app/forms/core/resolveSuite.ts
37
8
  var fieldKinds = [
38
9
  "string",
@@ -69,9 +40,38 @@ var resolveSuite = (overrides, fallback) => {
69
40
  };
70
41
  };
71
42
 
43
+ // src/app/forms/core/getFieldKind.ts
44
+ var hasSelectableValues = (field) => {
45
+ const possibleValues = field.possibleValues ?? [];
46
+ return possibleValues.some(
47
+ (value) => typeof value === "string" || typeof value === "number"
48
+ );
49
+ };
50
+ var getFieldKind = (field) => {
51
+ if (field.typeReference) {
52
+ return field.array ? "relation_array" : "relation_single";
53
+ }
54
+ if (field.tags?.customType) {
55
+ return field.array ? "custom_array" : "custom_single";
56
+ }
57
+ if (field.array) {
58
+ return "array";
59
+ }
60
+ if (hasSelectableValues(field)) {
61
+ return "enum_select";
62
+ }
63
+ if (field.type === "boolean") {
64
+ return "boolean";
65
+ }
66
+ if (field.type === "number") {
67
+ return "number";
68
+ }
69
+ return "string";
70
+ };
71
+
72
72
  // src/app/forms/core/createAutoField.ts
73
73
  var createAutoField = (suite) => {
74
- return (props) => {
74
+ const renderField = (props) => {
75
75
  const { field, fieldKey, value, onChange, error, disabled } = props;
76
76
  const { tags } = field;
77
77
  const context = {
@@ -89,11 +89,13 @@ var createAutoField = (suite) => {
89
89
  allowCustomSelection: tags?.allowCustomSelection,
90
90
  customType: tags?.customType,
91
91
  onRelationAction: props.onRelationAction,
92
- onCustomTypeAction: props.onCustomTypeAction
92
+ onCustomTypeAction: props.onCustomTypeAction,
93
+ renderField
93
94
  };
94
95
  const kind = getFieldKind(field);
95
96
  return suite.renderers[kind](context);
96
97
  };
98
+ return renderField;
97
99
  };
98
100
 
99
101
  // src/app/forms/core/createFormRenderer.ts
@@ -301,7 +303,6 @@ var renderCustomArray = (context) => {
301
303
  error ? createElement(ErrorMessage, null, error) : null
302
304
  );
303
305
  };
304
- var autoFieldRenderer;
305
306
  var renderArray = (context) => {
306
307
  const { field, fieldKey, label, required, disabled, error } = context;
307
308
  const itemField = createArrayItemField(field);
@@ -320,7 +321,7 @@ var renderArray = (context) => {
320
321
  createElement(
321
322
  View,
322
323
  { style: { flex: 1 } },
323
- autoFieldRenderer({
324
+ context.renderField({
324
325
  field: itemField,
325
326
  fieldKey: `${fieldKey}[${index}]`,
326
327
  value: item,
@@ -485,9 +486,9 @@ var nativeSuite = {
485
486
  Button: SuiteButton
486
487
  }
487
488
  };
488
- var resolvedNativeSuite = resolveSuite(void 0, nativeSuite);
489
- autoFieldRenderer = createAutoField(resolvedNativeSuite);
490
- var nativeAutoField = autoFieldRenderer;
489
+ var nativeAutoField = createFormRenderer({
490
+ fallbackSuite: nativeSuite
491
+ }).AutoField;
491
492
  var getDeniedOperation = (deniedOperations, operation) => {
492
493
  if (!deniedOperations) {
493
494
  return false;
@@ -720,6 +721,20 @@ var AutoForm2 = (props) => {
720
721
  };
721
722
 
722
723
  // src/app/utils/History.ts
724
+ var createHistoryBackHandler = (history) => {
725
+ return {
726
+ /**
727
+ * @returns True when back navigation was handled by history.
728
+ */
729
+ handle: () => {
730
+ if (history.index > 0) {
731
+ history.back();
732
+ return true;
733
+ }
734
+ return false;
735
+ }
736
+ };
737
+ };
723
738
  var ensurePrefix = (value, prefix) => value ? value.startsWith(prefix) ? value : `${prefix}${value}` : "";
724
739
  var parseHistoryPath = (inputPath) => {
725
740
  const raw = String(inputPath ?? "").trim();
@@ -1251,20 +1266,7 @@ var createNativeHistory = (options = {}) => {
1251
1266
  }
1252
1267
  };
1253
1268
  };
1254
- var createNativeBackHandler = (history) => {
1255
- return {
1256
- /**
1257
- * @returns True when back navigation was handled by history.
1258
- */
1259
- handle: () => {
1260
- if (history.index > 0) {
1261
- history.back();
1262
- return true;
1263
- }
1264
- return false;
1265
- }
1266
- };
1267
- };
1269
+ var createNativeBackHandler = (history) => createHistoryBackHandler(history);
1268
1270
 
1269
1271
  // src/common/Routing.ts
1270
1272
  var PATH_DELIMITER = "/";
@@ -1355,4 +1357,4 @@ var buildPathFromRouteChain = (routeChain, config, query) => {
1355
1357
  return buildRoutePath(segments, query);
1356
1358
  };
1357
1359
 
1358
- export { ArrayContainer, ArrayItemWrapper, AutoField, AutoForm2 as AutoForm, AutoFormView2 as AutoFormView, Button, ErrorMessage, FieldWrapper, NativeEasyLayoutView, buildHistoryPath, buildPathFromRouteChain, createMemoryHistory, createNativeBackHandler, createNativeFormRenderer, createNativeHistory, createNavigationStateRouteAdapter, makeNativeEasyLayout, mapNativeURLToPath, nativeAutoField, nativeSuite, parseHistoryPath, useNativeEasyLayout };
1360
+ export { ArrayContainer, ArrayItemWrapper, AutoField, AutoForm2 as AutoForm, AutoFormView2 as AutoFormView, Button, ErrorMessage, FieldWrapper, NativeEasyLayoutView, buildHistoryPath, buildPathFromRouteChain, createHistoryBackHandler, createMemoryHistory, createNativeBackHandler, createNativeFormRenderer, createNativeHistory, createNavigationStateRouteAdapter, makeNativeEasyLayout, mapNativeURLToPath, nativeAutoField, nativeSuite, parseHistoryPath, useNativeEasyLayout };
@@ -95,19 +95,8 @@ export declare const mapNativeURLToPath: (url: string) => string;
95
95
  */
96
96
  export declare const createNativeHistory: (options?: CreateNativeHistoryOptions) => NativeHistoryController;
97
97
  /**
98
- * Create an Android back-handler helper for native history.
99
- *
100
- * Returns `true` only when history consumed the back action.
101
- *
102
- * Example:
103
- * ```ts
104
- * const handler = createNativeBackHandler(history);
105
- * const consumed = handler.handle();
106
- * ```
98
+ * @deprecated Use {@link createHistoryBackHandler} from `app/utils/History`.
107
99
  */
108
100
  export declare const createNativeBackHandler: (history: HistoryController) => {
109
- /**
110
- * @returns True when back navigation was handled by history.
111
- */
112
101
  handle: () => boolean;
113
102
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resistdesign/voltra",
3
- "version": "3.0.0-alpha.25",
3
+ "version": "3.0.0-alpha.27",
4
4
  "description": "With our powers combined!",
5
5
  "homepage": "https://voltra.app",
6
6
  "repository": "git@github.com:resistdesign/voltra.git",
package/web/index.js CHANGED
@@ -21,35 +21,6 @@ var __copyProps = (to, from, except, desc) => {
21
21
  };
22
22
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget);
23
23
 
24
- // src/app/forms/core/getFieldKind.ts
25
- var hasSelectableValues = (field) => {
26
- const possibleValues = field.possibleValues ?? [];
27
- return possibleValues.some(
28
- (value) => typeof value === "string" || typeof value === "number"
29
- );
30
- };
31
- var getFieldKind = (field) => {
32
- if (field.typeReference) {
33
- return field.array ? "relation_array" : "relation_single";
34
- }
35
- if (field.tags?.customType) {
36
- return field.array ? "custom_array" : "custom_single";
37
- }
38
- if (field.array) {
39
- return "array";
40
- }
41
- if (hasSelectableValues(field)) {
42
- return "enum_select";
43
- }
44
- if (field.type === "boolean") {
45
- return "boolean";
46
- }
47
- if (field.type === "number") {
48
- return "number";
49
- }
50
- return "string";
51
- };
52
-
53
24
  // src/app/forms/core/resolveSuite.ts
54
25
  var fieldKinds = [
55
26
  "string",
@@ -86,9 +57,38 @@ var resolveSuite = (overrides, fallback) => {
86
57
  };
87
58
  };
88
59
 
60
+ // src/app/forms/core/getFieldKind.ts
61
+ var hasSelectableValues = (field) => {
62
+ const possibleValues = field.possibleValues ?? [];
63
+ return possibleValues.some(
64
+ (value) => typeof value === "string" || typeof value === "number"
65
+ );
66
+ };
67
+ var getFieldKind = (field) => {
68
+ if (field.typeReference) {
69
+ return field.array ? "relation_array" : "relation_single";
70
+ }
71
+ if (field.tags?.customType) {
72
+ return field.array ? "custom_array" : "custom_single";
73
+ }
74
+ if (field.array) {
75
+ return "array";
76
+ }
77
+ if (hasSelectableValues(field)) {
78
+ return "enum_select";
79
+ }
80
+ if (field.type === "boolean") {
81
+ return "boolean";
82
+ }
83
+ if (field.type === "number") {
84
+ return "number";
85
+ }
86
+ return "string";
87
+ };
88
+
89
89
  // src/app/forms/core/createAutoField.ts
90
90
  var createAutoField = (suite) => {
91
- return (props) => {
91
+ const renderField = (props) => {
92
92
  const { field, fieldKey, value, onChange, error, disabled } = props;
93
93
  const { tags } = field;
94
94
  const context = {
@@ -106,11 +106,13 @@ var createAutoField = (suite) => {
106
106
  allowCustomSelection: tags?.allowCustomSelection,
107
107
  customType: tags?.customType,
108
108
  onRelationAction: props.onRelationAction,
109
- onCustomTypeAction: props.onCustomTypeAction
109
+ onCustomTypeAction: props.onCustomTypeAction,
110
+ renderField
110
111
  };
111
112
  const kind = getFieldKind(field);
112
113
  return suite.renderers[kind](context);
113
114
  };
115
+ return renderField;
114
116
  };
115
117
 
116
118
  // src/app/forms/core/createFormRenderer.ts
@@ -348,7 +350,6 @@ var renderCustomArray = (context) => {
348
350
  error && /* @__PURE__ */ jsx(ErrorMessage, { children: error })
349
351
  ] });
350
352
  };
351
- var autoFieldRenderer;
352
353
  var renderArray = (context) => {
353
354
  const { field, fieldKey, label, required, disabled, error } = context;
354
355
  const id = `field-${fieldKey}`;
@@ -362,7 +363,7 @@ var renderArray = (context) => {
362
363
  ] }),
363
364
  /* @__PURE__ */ jsxs(ArrayContainer, { children: [
364
365
  arrayValue.map((item, index) => /* @__PURE__ */ jsxs(ArrayItemWrapper, { children: [
365
- /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: autoFieldRenderer({
366
+ /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: context.renderField({
366
367
  field: itemField,
367
368
  fieldKey: `${fieldKey}[${index}]`,
368
369
  value: item,
@@ -572,9 +573,9 @@ var webSuite = {
572
573
  Button: SuiteButton
573
574
  }
574
575
  };
575
- var resolvedWebSuite = resolveSuite(void 0, webSuite);
576
- autoFieldRenderer = createAutoField(resolvedWebSuite);
577
- var webAutoField = autoFieldRenderer;
576
+ var webAutoField = createFormRenderer({
577
+ fallbackSuite: webSuite
578
+ }).AutoField;
578
579
  var RelationList = styled_default("div")`
579
580
  display: flex;
580
581
  flex-direction: column;