@resistdesign/voltra 3.0.0-alpha.27 → 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,342 +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 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
- };
738
- var ensurePrefix = (value, prefix) => value ? value.startsWith(prefix) ? value : `${prefix}${value}` : "";
739
- var parseHistoryPath = (inputPath) => {
740
- const raw = String(inputPath ?? "").trim();
741
- if (!raw) {
742
- return { path: "/" };
743
- }
744
- try {
745
- const absoluteUrl = new URL(raw);
746
- return {
747
- path: absoluteUrl.pathname || "/",
748
- ...absoluteUrl.search ? { search: absoluteUrl.search } : {},
749
- ...absoluteUrl.hash ? { hash: absoluteUrl.hash } : {}
750
- };
751
- } catch (error) {
752
- let target = raw;
753
- let hash = "";
754
- let search = "";
755
- const hashIndex = target.indexOf("#");
756
- if (hashIndex >= 0) {
757
- hash = target.slice(hashIndex);
758
- target = target.slice(0, hashIndex);
759
- }
760
- const searchIndex = target.indexOf("?");
761
- if (searchIndex >= 0) {
762
- search = target.slice(searchIndex);
763
- target = target.slice(0, searchIndex);
764
- }
765
- const path = target ? target.startsWith("/") ? target : `/${target}` : "/";
766
- return {
767
- path,
768
- ...search && search !== "?" ? { search } : {},
769
- ...hash && hash !== "#" ? { hash } : {}
770
- };
771
- }
772
- };
773
- var buildHistoryPath = ({
774
- path,
775
- search,
776
- hash
777
- }) => {
778
- const normalizedPath = path ? path.startsWith("/") ? path : `/${path}` : "/";
779
- const normalizedSearch = search ? ensurePrefix(search, "?") : "";
780
- const normalizedHash = hash ? ensurePrefix(hash, "#") : "";
781
- return `${normalizedPath}${normalizedSearch}${normalizedHash}`;
782
- };
783
- var getHistoryLocation = (inputPath, state, getNextKey, currentLocation, replaceSearch = false) => {
784
- const parsed = parseHistoryPath(inputPath);
785
- const nextSearch = typeof parsed.search === "undefined" ? replaceSearch ? void 0 : currentLocation?.search : parsed.search;
786
- return {
787
- path: parsed.path,
788
- ...typeof nextSearch !== "undefined" ? { search: nextSearch } : {},
789
- ...parsed.hash ? { hash: parsed.hash } : {},
790
- ...typeof state !== "undefined" ? { state } : {},
791
- key: getNextKey()
792
- };
793
- };
794
- var createMemoryHistory = (initialPath = "/") => {
795
- let keyCounter = 0;
796
- const getNextKey = () => `h${keyCounter++}`;
797
- const listeners = /* @__PURE__ */ new Set();
798
- const entries = [
799
- {
800
- location: getHistoryLocation(
801
- initialPath,
802
- void 0,
803
- getNextKey,
804
- void 0,
805
- true
806
- )
807
- }
808
- ];
809
- let currentIndex = 0;
810
- const getCurrentLocation = () => entries[currentIndex].location;
811
- const notify = () => {
812
- const location = getCurrentLocation();
813
- listeners.forEach((listener) => listener(location));
814
- };
815
- const push = (path, opts) => {
816
- const location = getHistoryLocation(
817
- path,
818
- opts?.state,
819
- getNextKey,
820
- getCurrentLocation(),
821
- opts?.replaceSearch === true
822
- );
823
- if (currentIndex < entries.length - 1) {
824
- entries.splice(currentIndex + 1);
825
- }
826
- entries.push({ location });
827
- currentIndex = entries.length - 1;
828
- notify();
829
- };
830
- const replace = (path, opts) => {
831
- const location = getHistoryLocation(
832
- path,
833
- opts?.state,
834
- getNextKey,
835
- getCurrentLocation(),
836
- opts?.replaceSearch === true
837
- );
838
- entries[currentIndex] = { location };
839
- notify();
840
- };
841
- const go = (delta) => {
842
- if (!Number.isFinite(delta)) {
843
- return;
844
- }
845
- const targetIndex = Math.max(
846
- 0,
847
- Math.min(entries.length - 1, currentIndex + Math.trunc(delta))
848
- );
849
- if (targetIndex === currentIndex) {
850
- return;
851
- }
852
- currentIndex = targetIndex;
853
- notify();
854
- };
855
- return {
856
- get location() {
857
- return getCurrentLocation();
858
- },
859
- get length() {
860
- return entries.length;
861
- },
862
- get index() {
863
- return currentIndex;
864
- },
865
- push,
866
- replace,
867
- go,
868
- back: () => go(-1),
869
- forward: () => go(1),
870
- listen: (listener) => {
871
- listeners.add(listener);
872
- return () => listeners.delete(listener);
873
- }
874
- };
875
- };
876
-
877
- // src/app/utils/easy-layout/computeAreaBounds.ts
878
- var computeAreaBounds = (parsed) => {
879
- const result = {};
880
- for (let rowIndex = 0; rowIndex < parsed.areaGrid.length; rowIndex++) {
881
- const row = parsed.areaGrid[rowIndex];
882
- for (let colIndex = 0; colIndex < row.length; colIndex++) {
883
- const name = row[colIndex];
884
- if (!name || name === ".") {
885
- continue;
886
- }
887
- const row1 = rowIndex + 1;
888
- const col1 = colIndex + 1;
889
- const existing = result[name];
890
- if (!existing) {
891
- result[name] = {
892
- name,
893
- rowStart: row1,
894
- rowEnd: row1,
895
- colStart: col1,
896
- colEnd: col1
897
- };
898
- continue;
899
- }
900
- existing.rowStart = Math.min(existing.rowStart, row1);
901
- existing.rowEnd = Math.max(existing.rowEnd, row1);
902
- existing.colStart = Math.min(existing.colStart, col1);
903
- existing.colEnd = Math.max(existing.colEnd, col1);
904
- }
905
- }
906
- return result;
907
- };
908
-
909
- // src/app/utils/easy-layout/computeTracks.ts
910
- var computeTrackPixels = ({
911
- tracks,
912
- totalPx,
913
- gapPx = 0,
914
- paddingPx = 0
915
- }) => {
916
- if (!tracks.length) {
917
- return [];
918
- }
919
- const gapsPx = Math.max(0, tracks.length - 1) * Math.max(0, gapPx);
920
- const usablePx = Math.max(0, totalPx - Math.max(0, paddingPx) * 2 - gapsPx);
921
- let fixedPx = 0;
922
- let frTotal = 0;
923
- for (const track of tracks) {
924
- if (track.kind === "px") {
925
- fixedPx += track.value;
926
- } else if (track.kind === "pct") {
927
- fixedPx += usablePx * track.value / 100;
928
- } else {
929
- frTotal += track.value;
930
- }
931
- }
932
- const remainderPx = Math.max(0, usablePx - fixedPx);
933
- return tracks.map((track) => {
934
- if (track.kind === "px") {
935
- return track.value;
936
- }
937
- if (track.kind === "pct") {
938
- return usablePx * track.value / 100;
939
- }
940
- if (frTotal <= 0) {
941
- return 0;
942
- }
943
- return remainderPx * track.value / frTotal;
944
- });
945
- };
946
-
947
- // src/app/utils/easy-layout/parseTemplate.ts
948
- var parseTrackSpec = (token) => {
949
- const trimmed = token.trim();
950
- const numericMatch = trimmed.match(/^([0-9]*\.?[0-9]+)(fr|px|%)$/);
951
- if (!numericMatch) {
952
- throw new Error(
953
- `Invalid track token "${trimmed}". Supported units are fr, px, and %.`
954
- );
955
- }
956
- const value = Number(numericMatch[1]);
957
- const suffix = numericMatch[2];
958
- if (!Number.isFinite(value) || value < 0) {
959
- throw new Error(`Track value must be a non-negative number. Received "${trimmed}".`);
960
- }
961
- if (suffix === "fr") {
962
- return { kind: "fr", value };
963
- }
964
- if (suffix === "px") {
965
- return { kind: "px", value };
966
- }
967
- return { kind: "pct", value };
968
- };
969
- var normalizeAreas = (areaPart) => {
970
- return areaPart.trim().split(/\s+/g).map((token) => token.trim()).filter(Boolean);
971
- };
972
- var parseTemplate = (template = "") => {
973
- const lines = template.split("\n").map((line) => line.trim()).filter(Boolean);
974
- const areaGrid = [];
975
- const rowTracks = [];
976
- let colTracks = null;
977
- for (const line of lines) {
978
- if (line.startsWith("\\")) {
979
- if (colTracks) {
980
- throw new Error("Template can include only one column-track line.");
981
- }
982
- const colTokens = line.replace(/\\/g, " ").trim().split(/\s+/g).filter(Boolean);
983
- colTracks = colTokens.map(parseTrackSpec);
984
- continue;
985
- }
986
- const parts = line.split(",").map((part) => part.trim());
987
- const areaPart = parts[0] || "";
988
- if (!areaPart) {
989
- continue;
990
- }
991
- if (parts.length > 2) {
992
- throw new Error(
993
- `Invalid row definition "${line}". Expected "<areas>, <row-track>".`
994
- );
995
- }
996
- const areas = normalizeAreas(areaPart);
997
- if (!areas.length) {
998
- continue;
999
- }
1000
- areaGrid.push(areas);
1001
- const rowTrack = parts[1];
1002
- if (rowTrack) {
1003
- rowTracks.push(parseTrackSpec(rowTrack));
1004
- }
1005
- }
1006
- if (!areaGrid.length) {
1007
- throw new Error("Template must include at least one area row.");
1008
- }
1009
- const expectedWidth = areaGrid[0].length;
1010
- for (let rowIndex = 0; rowIndex < areaGrid.length; rowIndex++) {
1011
- const width = areaGrid[rowIndex].length;
1012
- if (width !== expectedWidth) {
1013
- throw new Error(
1014
- `All area rows must have the same width. Expected ${expectedWidth}, received ${width} at row ${rowIndex + 1}.`
1015
- );
1016
- }
1017
- }
1018
- if (colTracks && colTracks.length !== expectedWidth) {
1019
- throw new Error(
1020
- `Column track count must match area width. Expected ${expectedWidth}, received ${colTracks.length}.`
1021
- );
1022
- }
1023
- const areaNames = Array.from(
1024
- new Set(
1025
- areaGrid.flat().map((name) => name.trim()).filter((name) => !!name && name !== ".")
1026
- )
1027
- );
1028
- return {
1029
- areaGrid,
1030
- rowTracks,
1031
- colTracks: colTracks || [],
1032
- areaNames
1033
- };
1034
- };
1035
-
1036
- // src/app/utils/easy-layout/validateAreas.ts
1037
- var validateAreas = (parsed) => {
1038
- const bounds = computeAreaBounds(parsed);
1039
- for (const areaName of parsed.areaNames) {
1040
- const bound = bounds[areaName];
1041
- if (!bound) {
1042
- continue;
1043
- }
1044
- for (let row = bound.rowStart; row <= bound.rowEnd; row++) {
1045
- for (let col = bound.colStart; col <= bound.colEnd; col++) {
1046
- const token = parsed.areaGrid[row - 1]?.[col - 1];
1047
- if (token !== areaName) {
1048
- throw new Error(
1049
- `Area "${areaName}" must be a rectangle. Missing "${areaName}" at row ${row}, col ${col}.`
1050
- );
1051
- }
1052
- }
1053
- }
1054
- }
1055
- };
1056
-
1057
- // src/native/utils/EasyLayout.tsx
1058
417
  var roundTo = (value, decimals) => {
1059
418
  const places = Number.isFinite(decimals) ? Math.max(0, decimals) : 3;
1060
419
  const factor = Math.pow(10, places);
@@ -1267,60 +626,6 @@ var createNativeHistory = (options = {}) => {
1267
626
  };
1268
627
  };
1269
628
  var createNativeBackHandler = (history) => createHistoryBackHandler(history);
1270
-
1271
- // src/common/Routing.ts
1272
- var PATH_DELIMITER = "/";
1273
- var getPotentialJSONValue = (value) => {
1274
- try {
1275
- return JSON.parse(value);
1276
- } catch (error) {
1277
- return value;
1278
- }
1279
- };
1280
- 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);
1281
- 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);
1282
- var buildQueryString = (query = {}) => {
1283
- const parts = [];
1284
- for (const [key, rawValue] of Object.entries(query)) {
1285
- if (rawValue === void 0) {
1286
- continue;
1287
- }
1288
- const values = Array.isArray(rawValue) ? rawValue : [rawValue];
1289
- for (const value of values) {
1290
- if (value === void 0) {
1291
- continue;
1292
- }
1293
- const encodedKey = encodeURIComponent(key);
1294
- const encodedValue = value === null ? "" : encodeURIComponent(String(value));
1295
- parts.push(`${encodedKey}=${encodedValue}`);
1296
- }
1297
- }
1298
- return parts.join("&");
1299
- };
1300
- var buildRoutePath = (segments, query) => {
1301
- const normalizedSegments = segments.map((segment) => String(segment));
1302
- const basePath = "/" + getPathString(normalizedSegments, "/", true, false, true);
1303
- const queryString = query ? buildQueryString(query) : "";
1304
- return queryString ? `${basePath}?${queryString}` : basePath;
1305
- };
1306
- var RouteContext = createContext({
1307
- currentWindowPath: "",
1308
- parentPath: "",
1309
- params: {},
1310
- isTopLevel: true
1311
- });
1312
- var {
1313
- /**
1314
- * @ignore
1315
- */
1316
- Provider: RouteContextProvider,
1317
- /**
1318
- * @ignore
1319
- */
1320
- Consumer: RouteContextConsumer
1321
- } = RouteContext;
1322
-
1323
- // src/native/utils/Route.ts
1324
629
  var createNavigationStateRouteAdapter = (options) => {
1325
630
  const getPath = () => options.toPath(options.getState());
1326
631
  return {
@@ -1332,6 +637,58 @@ var createNavigationStateRouteAdapter = (options) => {
1332
637
  replace: options.replace ? (path) => options.replace?.(path) : void 0
1333
638
  };
1334
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
+ };
1335
692
  var expandPattern = (pattern, params = {}) => {
1336
693
  const segments = getPathArray(pattern, "/", true, true, false, false);
1337
694
  return segments.map((segment) => {
@@ -1357,4 +714,4 @@ var buildPathFromRouteChain = (routeChain, config, query) => {
1357
714
  return buildRoutePath(segments, query);
1358
715
  };
1359
716
 
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 };
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 };