@resistdesign/voltra 3.0.0-alpha.26 → 3.0.0-alpha.28

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/native/index.js CHANGED
@@ -1,115 +1,13 @@
1
- import { createContext, createElement, useMemo, useEffect, useState, useCallback } from 'react';
2
- import { View, Text, Pressable, TextInput, Switch, Platform } from 'react-native';
3
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
1
+ import { createHistoryBackHandler, buildHistoryPath, parseHistoryPath, createMemoryHistory, Route, buildRoutePath, computeTrackPixels } from '../chunk-G5CLUK4Y.js';
2
+ export { buildHistoryPath, createHistoryBackHandler, createMemoryHistory, parseHistoryPath, useRouteContext } from '../chunk-G5CLUK4Y.js';
3
+ import { createFormRenderer, AutoFormView, AutoForm, parseTemplate, validateAreas, computeAreaBounds } from '../chunk-WELZGQDJ.js';
4
+ import '../chunk-IWRHGGGH.js';
5
+ import { getPathArray } from '../chunk-GYWRAW3Y.js';
6
+ import '../chunk-I2KLQ2HA.js';
7
+ import { createElement, useMemo } from 'react';
8
+ import { Text, View, Platform, Switch, TextInput, Pressable, BackHandler } from 'react-native';
9
+ import { jsx } from 'react/jsx-runtime';
4
10
 
5
- // src/native/forms/suite.ts
6
-
7
- // src/app/forms/core/resolveSuite.ts
8
- var fieldKinds = [
9
- "string",
10
- "number",
11
- "boolean",
12
- "enum_select",
13
- "array",
14
- "relation_single",
15
- "relation_array",
16
- "custom_single",
17
- "custom_array"
18
- ];
19
- var getMissingKinds = (renderers) => {
20
- return fieldKinds.filter((kind) => !renderers[kind]);
21
- };
22
- var resolveSuite = (overrides, fallback) => {
23
- const mergedRenderers = {
24
- ...fallback.renderers ?? {},
25
- ...overrides?.renderers ?? {}
26
- };
27
- const missingKinds = getMissingKinds(mergedRenderers);
28
- if (missingKinds.length) {
29
- throw new Error(
30
- `Missing renderers for field kinds: ${missingKinds.join(", ")}`
31
- );
32
- }
33
- const mergedPrimitives = {
34
- ...fallback.primitives ?? {},
35
- ...overrides?.primitives ?? {}
36
- };
37
- return {
38
- renderers: mergedRenderers,
39
- primitives: Object.keys(mergedPrimitives).length ? mergedPrimitives : void 0
40
- };
41
- };
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
- // src/app/forms/core/createAutoField.ts
73
- var createAutoField = (suite) => {
74
- const renderField = (props) => {
75
- const { field, fieldKey, value, onChange, error, disabled } = props;
76
- const { tags } = field;
77
- const context = {
78
- field,
79
- fieldKey,
80
- label: tags?.label ?? fieldKey,
81
- required: !field.optional,
82
- disabled: !!disabled,
83
- error,
84
- value,
85
- onChange,
86
- constraints: tags?.constraints,
87
- format: tags?.format,
88
- possibleValues: field.possibleValues,
89
- allowCustomSelection: tags?.allowCustomSelection,
90
- customType: tags?.customType,
91
- onRelationAction: props.onRelationAction,
92
- onCustomTypeAction: props.onCustomTypeAction,
93
- renderField
94
- };
95
- const kind = getFieldKind(field);
96
- return suite.renderers[kind](context);
97
- };
98
- return renderField;
99
- };
100
-
101
- // src/app/forms/core/createFormRenderer.ts
102
- var createFormRenderer = (options) => {
103
- const resolvedSuite = resolveSuite(
104
- options.suite,
105
- options.fallbackSuite
106
- );
107
- const AutoField2 = createAutoField(resolvedSuite);
108
- return {
109
- AutoField: AutoField2,
110
- suite: resolvedSuite
111
- };
112
- };
113
11
  var FieldWrapper = (props) => {
114
12
  return createElement(View, null, props.children);
115
13
  };
@@ -489,209 +387,6 @@ var nativeSuite = {
489
387
  var nativeAutoField = createFormRenderer({
490
388
  fallbackSuite: nativeSuite
491
389
  }).AutoField;
492
- var getDeniedOperation = (deniedOperations, operation) => {
493
- if (!deniedOperations) {
494
- return false;
495
- }
496
- const denied = deniedOperations[operation];
497
- if (typeof denied === "boolean") {
498
- return denied;
499
- }
500
- return deniedOperations[operation.toLowerCase()] ?? false;
501
- };
502
- var buildInitialValues = (initialValues, typeInfo) => {
503
- const values = { ...initialValues };
504
- for (const [key, field] of Object.entries(typeInfo.fields ?? {})) {
505
- if (values[key] !== void 0) {
506
- continue;
507
- }
508
- const defaultValue = field.tags?.constraints?.defaultValue;
509
- if (defaultValue !== void 0) {
510
- let parsedDefaultValue = defaultValue;
511
- try {
512
- parsedDefaultValue = JSON.parse(defaultValue);
513
- } catch (error) {
514
- }
515
- values[key] = parsedDefaultValue;
516
- continue;
517
- }
518
- if (field.array && !field.typeReference && !field.optional) {
519
- values[key] = [];
520
- continue;
521
- }
522
- if (field.type === "boolean" && !field.optional) {
523
- values[key] = false;
524
- }
525
- }
526
- return values;
527
- };
528
- var useFormEngine = (initialValues = {}, typeInfo, options) => {
529
- const operation = options?.operation ?? "CREATE" /* CREATE */;
530
- const [values, setValues] = useState(
531
- buildInitialValues(initialValues, typeInfo)
532
- );
533
- const [errors, setErrors] = useState({});
534
- const setFieldValue = useCallback((path, value) => {
535
- setValues((prev) => {
536
- return {
537
- ...prev,
538
- [path]: value
539
- };
540
- });
541
- }, []);
542
- const validate = useCallback(() => {
543
- const newErrors = {};
544
- for (const [key, field] of Object.entries(typeInfo.fields ?? {})) {
545
- if (field.tags?.hidden) {
546
- continue;
547
- }
548
- const val = values[key];
549
- if (field.readonly && (val === void 0 || val === null || val === "")) {
550
- continue;
551
- }
552
- const isMissing = val === void 0 || val === null || val === "" || field.array && (!Array.isArray(val) || val.length === 0);
553
- if (!field.optional && isMissing) {
554
- newErrors[key] = "This field is required";
555
- continue;
556
- }
557
- if (isMissing) {
558
- continue;
559
- }
560
- const constraints = field.tags?.constraints;
561
- if (constraints?.pattern && typeof val === "string") {
562
- const pattern = new RegExp(constraints.pattern);
563
- if (!pattern.test(val)) {
564
- newErrors[key] = "Value does not match required pattern";
565
- continue;
566
- }
567
- }
568
- if (field.type === "number" && typeof val === "number") {
569
- if (constraints?.min !== void 0 && val < constraints.min) {
570
- newErrors[key] = `Value must be at least ${constraints.min}`;
571
- continue;
572
- }
573
- if (constraints?.max !== void 0 && val > constraints.max) {
574
- newErrors[key] = `Value must be at most ${constraints.max}`;
575
- continue;
576
- }
577
- }
578
- }
579
- setErrors(newErrors);
580
- return Object.keys(newErrors).length === 0;
581
- }, [typeInfo, values]);
582
- const fields = useMemo(() => {
583
- return Object.entries(typeInfo.fields ?? {}).map(([key, field]) => {
584
- const { tags } = field;
585
- const isPrimary = tags?.primaryField || typeInfo.primaryField === key;
586
- return {
587
- key,
588
- field,
589
- label: tags?.label ?? key,
590
- required: !field.optional,
591
- disabled: field.readonly || getDeniedOperation(typeInfo.tags?.deniedOperations, operation) || getDeniedOperation(tags?.deniedOperations, operation) || operation === "UPDATE" /* UPDATE */ && isPrimary,
592
- hidden: !!tags?.hidden,
593
- primary: isPrimary,
594
- format: tags?.format,
595
- constraints: tags?.constraints,
596
- value: values[key],
597
- onChange: (value) => setFieldValue(key, value),
598
- error: errors[key]
599
- };
600
- });
601
- }, [typeInfo, values, errors, setFieldValue, operation]);
602
- return {
603
- typeInfo,
604
- typeTags: typeInfo.tags,
605
- operation,
606
- values,
607
- errors,
608
- fields,
609
- setFieldValue,
610
- validate,
611
- setErrors
612
- };
613
- };
614
- var fallbackFormRoot = ({
615
- children,
616
- onSubmit
617
- }) => {
618
- const handleSubmit = (event) => {
619
- event.preventDefault();
620
- onSubmit?.();
621
- };
622
- return /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children });
623
- };
624
- var fallbackButton = ({
625
- children,
626
- disabled,
627
- type,
628
- onClick
629
- }) => {
630
- return /* @__PURE__ */ jsx("button", { type: type ?? "button", disabled, onClick, children });
631
- };
632
- var AutoFormView = ({
633
- controller,
634
- onSubmit,
635
- renderer,
636
- submitDisabled,
637
- onRelationAction,
638
- onCustomTypeAction
639
- }) => {
640
- const FormRoot2 = renderer.suite.primitives?.FormRoot ?? fallbackFormRoot;
641
- const Button2 = renderer.suite.primitives?.Button ?? fallbackButton;
642
- const AutoField2 = renderer.AutoField;
643
- const submit = () => {
644
- if (controller.validate()) {
645
- onSubmit(controller.values);
646
- }
647
- };
648
- return /* @__PURE__ */ jsx(FormRoot2, { onSubmit: submit, children: /* @__PURE__ */ jsxs(Fragment, { children: [
649
- controller.fields.filter((fieldController) => !fieldController.hidden).map((fieldController) => /* @__PURE__ */ jsx(
650
- AutoField2,
651
- {
652
- field: fieldController.field,
653
- fieldKey: fieldController.key,
654
- value: fieldController.value,
655
- onChange: fieldController.onChange,
656
- error: fieldController.error,
657
- onRelationAction,
658
- disabled: fieldController.disabled,
659
- onCustomTypeAction
660
- },
661
- fieldController.key
662
- )),
663
- /* @__PURE__ */ jsx(Button2, { type: "submit", onClick: submit, disabled: submitDisabled, children: /* @__PURE__ */ jsx(Fragment, { children: "Submit" }) })
664
- ] }) });
665
- };
666
- var AutoForm = ({
667
- typeInfo,
668
- onSubmit,
669
- renderer,
670
- initialValues,
671
- onValuesChange,
672
- onRelationAction,
673
- onCustomTypeAction,
674
- operation,
675
- submitDisabled
676
- }) => {
677
- const controller = useFormEngine(initialValues, typeInfo, { operation });
678
- useEffect(() => {
679
- if (onValuesChange) {
680
- onValuesChange(controller.values);
681
- }
682
- }, [controller.values, onValuesChange]);
683
- return /* @__PURE__ */ jsx(
684
- AutoFormView,
685
- {
686
- controller,
687
- onSubmit,
688
- renderer,
689
- onRelationAction,
690
- onCustomTypeAction,
691
- submitDisabled
692
- }
693
- );
694
- };
695
390
 
696
391
  // src/native/forms/createNativeFormRenderer.ts
697
392
  var createNativeFormRenderer = (options) => {
@@ -719,328 +414,6 @@ var AutoFormView2 = (props) => {
719
414
  var AutoForm2 = (props) => {
720
415
  return /* @__PURE__ */ jsx(AutoForm, { ...props, renderer: defaultNativeRenderer });
721
416
  };
722
-
723
- // src/app/utils/History.ts
724
- var ensurePrefix = (value, prefix) => value ? value.startsWith(prefix) ? value : `${prefix}${value}` : "";
725
- var parseHistoryPath = (inputPath) => {
726
- const raw = String(inputPath ?? "").trim();
727
- if (!raw) {
728
- return { path: "/" };
729
- }
730
- try {
731
- const absoluteUrl = new URL(raw);
732
- return {
733
- path: absoluteUrl.pathname || "/",
734
- ...absoluteUrl.search ? { search: absoluteUrl.search } : {},
735
- ...absoluteUrl.hash ? { hash: absoluteUrl.hash } : {}
736
- };
737
- } catch (error) {
738
- let target = raw;
739
- let hash = "";
740
- let search = "";
741
- const hashIndex = target.indexOf("#");
742
- if (hashIndex >= 0) {
743
- hash = target.slice(hashIndex);
744
- target = target.slice(0, hashIndex);
745
- }
746
- const searchIndex = target.indexOf("?");
747
- if (searchIndex >= 0) {
748
- search = target.slice(searchIndex);
749
- target = target.slice(0, searchIndex);
750
- }
751
- const path = target ? target.startsWith("/") ? target : `/${target}` : "/";
752
- return {
753
- path,
754
- ...search && search !== "?" ? { search } : {},
755
- ...hash && hash !== "#" ? { hash } : {}
756
- };
757
- }
758
- };
759
- var buildHistoryPath = ({
760
- path,
761
- search,
762
- hash
763
- }) => {
764
- const normalizedPath = path ? path.startsWith("/") ? path : `/${path}` : "/";
765
- const normalizedSearch = search ? ensurePrefix(search, "?") : "";
766
- const normalizedHash = hash ? ensurePrefix(hash, "#") : "";
767
- return `${normalizedPath}${normalizedSearch}${normalizedHash}`;
768
- };
769
- var getHistoryLocation = (inputPath, state, getNextKey, currentLocation, replaceSearch = false) => {
770
- const parsed = parseHistoryPath(inputPath);
771
- const nextSearch = typeof parsed.search === "undefined" ? replaceSearch ? void 0 : currentLocation?.search : parsed.search;
772
- return {
773
- path: parsed.path,
774
- ...typeof nextSearch !== "undefined" ? { search: nextSearch } : {},
775
- ...parsed.hash ? { hash: parsed.hash } : {},
776
- ...typeof state !== "undefined" ? { state } : {},
777
- key: getNextKey()
778
- };
779
- };
780
- var createMemoryHistory = (initialPath = "/") => {
781
- let keyCounter = 0;
782
- const getNextKey = () => `h${keyCounter++}`;
783
- const listeners = /* @__PURE__ */ new Set();
784
- const entries = [
785
- {
786
- location: getHistoryLocation(
787
- initialPath,
788
- void 0,
789
- getNextKey,
790
- void 0,
791
- true
792
- )
793
- }
794
- ];
795
- let currentIndex = 0;
796
- const getCurrentLocation = () => entries[currentIndex].location;
797
- const notify = () => {
798
- const location = getCurrentLocation();
799
- listeners.forEach((listener) => listener(location));
800
- };
801
- const push = (path, opts) => {
802
- const location = getHistoryLocation(
803
- path,
804
- opts?.state,
805
- getNextKey,
806
- getCurrentLocation(),
807
- opts?.replaceSearch === true
808
- );
809
- if (currentIndex < entries.length - 1) {
810
- entries.splice(currentIndex + 1);
811
- }
812
- entries.push({ location });
813
- currentIndex = entries.length - 1;
814
- notify();
815
- };
816
- const replace = (path, opts) => {
817
- const location = getHistoryLocation(
818
- path,
819
- opts?.state,
820
- getNextKey,
821
- getCurrentLocation(),
822
- opts?.replaceSearch === true
823
- );
824
- entries[currentIndex] = { location };
825
- notify();
826
- };
827
- const go = (delta) => {
828
- if (!Number.isFinite(delta)) {
829
- return;
830
- }
831
- const targetIndex = Math.max(
832
- 0,
833
- Math.min(entries.length - 1, currentIndex + Math.trunc(delta))
834
- );
835
- if (targetIndex === currentIndex) {
836
- return;
837
- }
838
- currentIndex = targetIndex;
839
- notify();
840
- };
841
- return {
842
- get location() {
843
- return getCurrentLocation();
844
- },
845
- get length() {
846
- return entries.length;
847
- },
848
- get index() {
849
- return currentIndex;
850
- },
851
- push,
852
- replace,
853
- go,
854
- back: () => go(-1),
855
- forward: () => go(1),
856
- listen: (listener) => {
857
- listeners.add(listener);
858
- return () => listeners.delete(listener);
859
- }
860
- };
861
- };
862
-
863
- // src/app/utils/easy-layout/computeAreaBounds.ts
864
- var computeAreaBounds = (parsed) => {
865
- const result = {};
866
- for (let rowIndex = 0; rowIndex < parsed.areaGrid.length; rowIndex++) {
867
- const row = parsed.areaGrid[rowIndex];
868
- for (let colIndex = 0; colIndex < row.length; colIndex++) {
869
- const name = row[colIndex];
870
- if (!name || name === ".") {
871
- continue;
872
- }
873
- const row1 = rowIndex + 1;
874
- const col1 = colIndex + 1;
875
- const existing = result[name];
876
- if (!existing) {
877
- result[name] = {
878
- name,
879
- rowStart: row1,
880
- rowEnd: row1,
881
- colStart: col1,
882
- colEnd: col1
883
- };
884
- continue;
885
- }
886
- existing.rowStart = Math.min(existing.rowStart, row1);
887
- existing.rowEnd = Math.max(existing.rowEnd, row1);
888
- existing.colStart = Math.min(existing.colStart, col1);
889
- existing.colEnd = Math.max(existing.colEnd, col1);
890
- }
891
- }
892
- return result;
893
- };
894
-
895
- // src/app/utils/easy-layout/computeTracks.ts
896
- var computeTrackPixels = ({
897
- tracks,
898
- totalPx,
899
- gapPx = 0,
900
- paddingPx = 0
901
- }) => {
902
- if (!tracks.length) {
903
- return [];
904
- }
905
- const gapsPx = Math.max(0, tracks.length - 1) * Math.max(0, gapPx);
906
- const usablePx = Math.max(0, totalPx - Math.max(0, paddingPx) * 2 - gapsPx);
907
- let fixedPx = 0;
908
- let frTotal = 0;
909
- for (const track of tracks) {
910
- if (track.kind === "px") {
911
- fixedPx += track.value;
912
- } else if (track.kind === "pct") {
913
- fixedPx += usablePx * track.value / 100;
914
- } else {
915
- frTotal += track.value;
916
- }
917
- }
918
- const remainderPx = Math.max(0, usablePx - fixedPx);
919
- return tracks.map((track) => {
920
- if (track.kind === "px") {
921
- return track.value;
922
- }
923
- if (track.kind === "pct") {
924
- return usablePx * track.value / 100;
925
- }
926
- if (frTotal <= 0) {
927
- return 0;
928
- }
929
- return remainderPx * track.value / frTotal;
930
- });
931
- };
932
-
933
- // src/app/utils/easy-layout/parseTemplate.ts
934
- var parseTrackSpec = (token) => {
935
- const trimmed = token.trim();
936
- const numericMatch = trimmed.match(/^([0-9]*\.?[0-9]+)(fr|px|%)$/);
937
- if (!numericMatch) {
938
- throw new Error(
939
- `Invalid track token "${trimmed}". Supported units are fr, px, and %.`
940
- );
941
- }
942
- const value = Number(numericMatch[1]);
943
- const suffix = numericMatch[2];
944
- if (!Number.isFinite(value) || value < 0) {
945
- throw new Error(`Track value must be a non-negative number. Received "${trimmed}".`);
946
- }
947
- if (suffix === "fr") {
948
- return { kind: "fr", value };
949
- }
950
- if (suffix === "px") {
951
- return { kind: "px", value };
952
- }
953
- return { kind: "pct", value };
954
- };
955
- var normalizeAreas = (areaPart) => {
956
- return areaPart.trim().split(/\s+/g).map((token) => token.trim()).filter(Boolean);
957
- };
958
- var parseTemplate = (template = "") => {
959
- const lines = template.split("\n").map((line) => line.trim()).filter(Boolean);
960
- const areaGrid = [];
961
- const rowTracks = [];
962
- let colTracks = null;
963
- for (const line of lines) {
964
- if (line.startsWith("\\")) {
965
- if (colTracks) {
966
- throw new Error("Template can include only one column-track line.");
967
- }
968
- const colTokens = line.replace(/\\/g, " ").trim().split(/\s+/g).filter(Boolean);
969
- colTracks = colTokens.map(parseTrackSpec);
970
- continue;
971
- }
972
- const parts = line.split(",").map((part) => part.trim());
973
- const areaPart = parts[0] || "";
974
- if (!areaPart) {
975
- continue;
976
- }
977
- if (parts.length > 2) {
978
- throw new Error(
979
- `Invalid row definition "${line}". Expected "<areas>, <row-track>".`
980
- );
981
- }
982
- const areas = normalizeAreas(areaPart);
983
- if (!areas.length) {
984
- continue;
985
- }
986
- areaGrid.push(areas);
987
- const rowTrack = parts[1];
988
- if (rowTrack) {
989
- rowTracks.push(parseTrackSpec(rowTrack));
990
- }
991
- }
992
- if (!areaGrid.length) {
993
- throw new Error("Template must include at least one area row.");
994
- }
995
- const expectedWidth = areaGrid[0].length;
996
- for (let rowIndex = 0; rowIndex < areaGrid.length; rowIndex++) {
997
- const width = areaGrid[rowIndex].length;
998
- if (width !== expectedWidth) {
999
- throw new Error(
1000
- `All area rows must have the same width. Expected ${expectedWidth}, received ${width} at row ${rowIndex + 1}.`
1001
- );
1002
- }
1003
- }
1004
- if (colTracks && colTracks.length !== expectedWidth) {
1005
- throw new Error(
1006
- `Column track count must match area width. Expected ${expectedWidth}, received ${colTracks.length}.`
1007
- );
1008
- }
1009
- const areaNames = Array.from(
1010
- new Set(
1011
- areaGrid.flat().map((name) => name.trim()).filter((name) => !!name && name !== ".")
1012
- )
1013
- );
1014
- return {
1015
- areaGrid,
1016
- rowTracks,
1017
- colTracks: colTracks || [],
1018
- areaNames
1019
- };
1020
- };
1021
-
1022
- // src/app/utils/easy-layout/validateAreas.ts
1023
- var validateAreas = (parsed) => {
1024
- const bounds = computeAreaBounds(parsed);
1025
- for (const areaName of parsed.areaNames) {
1026
- const bound = bounds[areaName];
1027
- if (!bound) {
1028
- continue;
1029
- }
1030
- for (let row = bound.rowStart; row <= bound.rowEnd; row++) {
1031
- for (let col = bound.colStart; col <= bound.colEnd; col++) {
1032
- const token = parsed.areaGrid[row - 1]?.[col - 1];
1033
- if (token !== areaName) {
1034
- throw new Error(
1035
- `Area "${areaName}" must be a rectangle. Missing "${areaName}" at row ${row}, col ${col}.`
1036
- );
1037
- }
1038
- }
1039
- }
1040
- }
1041
- };
1042
-
1043
- // src/native/utils/EasyLayout.tsx
1044
417
  var roundTo = (value, decimals) => {
1045
418
  const places = Number.isFinite(decimals) ? Math.max(0, decimals) : 3;
1046
419
  const factor = Math.pow(10, places);
@@ -1252,74 +625,7 @@ var createNativeHistory = (options = {}) => {
1252
625
  }
1253
626
  };
1254
627
  };
1255
- var createNativeBackHandler = (history) => {
1256
- return {
1257
- /**
1258
- * @returns True when back navigation was handled by history.
1259
- */
1260
- handle: () => {
1261
- if (history.index > 0) {
1262
- history.back();
1263
- return true;
1264
- }
1265
- return false;
1266
- }
1267
- };
1268
- };
1269
-
1270
- // src/common/Routing.ts
1271
- var PATH_DELIMITER = "/";
1272
- var getPotentialJSONValue = (value) => {
1273
- try {
1274
- return JSON.parse(value);
1275
- } catch (error) {
1276
- return value;
1277
- }
1278
- };
1279
- var getPathArray = (path, delimiter = PATH_DELIMITER, filterEmptyOutput = false, filterEmptyInput = true, useJson = true, uriDecodeParts = true) => path.split(delimiter).filter(filterEmptyInput ? (p) => p !== "" : () => true).map(uriDecodeParts ? decodeURIComponent : (x) => x).map(useJson ? getPotentialJSONValue : (p) => p).filter(filterEmptyOutput ? (p) => p ?? false : () => true);
1280
- var getPathString = (parts = [], delimiter = PATH_DELIMITER, filterEmptyInput = false, useJson = true, uriEncodeParts = false) => parts.filter(filterEmptyInput ? (p) => p ?? false : () => true).map(useJson ? (p) => JSON.stringify(p) : (x) => x).map(uriEncodeParts ? encodeURIComponent : (x) => x).join(delimiter);
1281
- var buildQueryString = (query = {}) => {
1282
- const parts = [];
1283
- for (const [key, rawValue] of Object.entries(query)) {
1284
- if (rawValue === void 0) {
1285
- continue;
1286
- }
1287
- const values = Array.isArray(rawValue) ? rawValue : [rawValue];
1288
- for (const value of values) {
1289
- if (value === void 0) {
1290
- continue;
1291
- }
1292
- const encodedKey = encodeURIComponent(key);
1293
- const encodedValue = value === null ? "" : encodeURIComponent(String(value));
1294
- parts.push(`${encodedKey}=${encodedValue}`);
1295
- }
1296
- }
1297
- return parts.join("&");
1298
- };
1299
- var buildRoutePath = (segments, query) => {
1300
- const normalizedSegments = segments.map((segment) => String(segment));
1301
- const basePath = "/" + getPathString(normalizedSegments, "/", true, false, true);
1302
- const queryString = query ? buildQueryString(query) : "";
1303
- return queryString ? `${basePath}?${queryString}` : basePath;
1304
- };
1305
- var RouteContext = createContext({
1306
- currentWindowPath: "",
1307
- parentPath: "",
1308
- params: {},
1309
- isTopLevel: true
1310
- });
1311
- var {
1312
- /**
1313
- * @ignore
1314
- */
1315
- Provider: RouteContextProvider,
1316
- /**
1317
- * @ignore
1318
- */
1319
- Consumer: RouteContextConsumer
1320
- } = RouteContext;
1321
-
1322
- // src/native/utils/Route.ts
628
+ var createNativeBackHandler = (history) => createHistoryBackHandler(history);
1323
629
  var createNavigationStateRouteAdapter = (options) => {
1324
630
  const getPath = () => options.toPath(options.getState());
1325
631
  return {
@@ -1331,6 +637,58 @@ var createNavigationStateRouteAdapter = (options) => {
1331
637
  replace: options.replace ? (path) => options.replace?.(path) : void 0
1332
638
  };
1333
639
  };
640
+ var createNativeHardwareBackHandler = (adapter) => {
641
+ return () => {
642
+ if (adapter.canGoBack?.()) {
643
+ adapter.back?.();
644
+ return true;
645
+ }
646
+ return false;
647
+ };
648
+ };
649
+ var registerNativeHardwareBackHandler = (adapter, backHandler) => {
650
+ const listener = createNativeHardwareBackHandler(adapter);
651
+ const subscription = backHandler.addEventListener(
652
+ "hardwareBackPress",
653
+ listener
654
+ );
655
+ return () => {
656
+ if (typeof subscription?.remove === "function") {
657
+ subscription.remove();
658
+ return;
659
+ }
660
+ backHandler.removeEventListener?.("hardwareBackPress", listener);
661
+ };
662
+ };
663
+ var createNativeRouteBackIntegration = (backHandler) => {
664
+ return {
665
+ setup: (adapter) => registerNativeHardwareBackHandler(adapter, backHandler)
666
+ };
667
+ };
668
+ var Route2 = (props) => {
669
+ const hasMatcherProps = typeof props.path !== "undefined" || typeof props.exact !== "undefined" || typeof props.onParamsChange !== "undefined";
670
+ const nativeRuntime = {
671
+ platformOS: String(Platform?.OS ?? ""),
672
+ backHandler: BackHandler
673
+ };
674
+ const runtimeIntegration = (() => {
675
+ if (hasMatcherProps || nativeRuntime.platformOS === "web") {
676
+ return void 0;
677
+ }
678
+ const backHandler = nativeRuntime.backHandler;
679
+ if (!backHandler) {
680
+ return void 0;
681
+ }
682
+ return createNativeRouteBackIntegration(backHandler);
683
+ })();
684
+ return /* @__PURE__ */ jsx(
685
+ Route,
686
+ {
687
+ ...props,
688
+ runtimeIntegration
689
+ }
690
+ );
691
+ };
1334
692
  var expandPattern = (pattern, params = {}) => {
1335
693
  const segments = getPathArray(pattern, "/", true, true, false, false);
1336
694
  return segments.map((segment) => {
@@ -1356,4 +714,4 @@ var buildPathFromRouteChain = (routeChain, config, query) => {
1356
714
  return buildRoutePath(segments, query);
1357
715
  };
1358
716
 
1359
- 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 };
717
+ export { ArrayContainer, ArrayItemWrapper, AutoField, AutoForm2 as AutoForm, AutoFormView2 as AutoFormView, Button, ErrorMessage, FieldWrapper, NativeEasyLayoutView, Route2 as Route, buildPathFromRouteChain, createNativeBackHandler, createNativeFormRenderer, createNativeHardwareBackHandler, createNativeHistory, createNativeRouteBackIntegration, createNavigationStateRouteAdapter, makeNativeEasyLayout, mapNativeURLToPath, nativeAutoField, nativeSuite, registerNativeHardwareBackHandler, useNativeEasyLayout };