@developer_tribe/react-builder 1.2.45 → 1.2.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attributes-editor/Field.d.ts +3 -1
- package/dist/attributes-editor/attributesEditorModelTypes.d.ts +3 -0
- package/dist/attributes-editor/useAttributesEditorModel.d.ts +1 -1
- package/dist/build-components/FormSubmitButton/FormSubmitButtonProps.generated.d.ts +8 -3
- package/dist/build-components/GlobalProvider/GlobalContext.d.ts +28 -0
- package/dist/build-components/GlobalProvider/GlobalProvider.d.ts +5 -0
- package/dist/build-components/GlobalProvider/GlobalProviderProps.generated.d.ts +60 -0
- package/dist/build-components/GlobalProvider/globalProviderUtils.d.ts +28 -0
- package/dist/build-components/GlobalProvider/useGlobalNavigation.d.ts +19 -0
- package/dist/build-components/GlobalProvider/useGlobalProviderLogic.d.ts +15 -0
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +8 -3
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
- package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -0
- package/dist/build-components/SystemButton/SystemButtonProps.generated.d.ts +8 -3
- package/dist/build-components/SystemButton/usePlacementButtonEvents.d.ts +15 -2
- package/dist/build-components/TermsProvider/TermsProvider.d.ts +5 -0
- package/dist/build-components/TermsProvider/TermsProviderProps.generated.d.ts +55 -0
- package/dist/build-components/index.d.ts +3 -1
- package/dist/build-components/patterns.generated.d.ts +2128 -1333
- package/dist/index.cjs.js +3 -3
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +3 -3
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +3 -3
- package/dist/index.web.esm.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils/nodeTree.d.ts +18 -0
- package/package.json +1 -1
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +68 -4
- package/src/assets/meta.json +1 -1
- package/src/assets/prompt-scheme-onboard.generated.ts +1 -1
- package/src/assets/prompt-scheme-paywall.generated.ts +1 -1
- package/src/assets/samples/getSamples.ts +2 -0
- package/src/assets/samples/global-onboard-flow.json +735 -0
- package/src/assets/samples/terms-and-privacy-no-form.json +1 -1
- package/src/assets/samples/terms-and-privacy.json +1 -1
- package/src/attributes-editor/AttributesEditorView.tsx +3 -0
- package/src/attributes-editor/Field.tsx +91 -2
- package/src/attributes-editor/attributesEditorModelTypes.ts +3 -0
- package/src/attributes-editor/useAttributesEditorModel.ts +8 -0
- package/src/build-components/FormCheckbox/FormCheckbox.tsx +3 -3
- package/src/build-components/FormSubmitButton/FormSubmitButton.tsx +6 -0
- package/src/build-components/FormSubmitButton/FormSubmitButtonProps.generated.ts +26 -3
- package/src/build-components/GlobalProvider/GlobalContext.ts +48 -0
- package/src/build-components/GlobalProvider/GlobalProvider.tsx +51 -0
- package/src/build-components/GlobalProvider/GlobalProviderProps.generated.ts +78 -0
- package/src/build-components/GlobalProvider/globalProviderUtils.ts +204 -0
- package/src/build-components/GlobalProvider/pattern.json +55 -0
- package/src/build-components/GlobalProvider/useGlobalNavigation.ts +65 -0
- package/src/build-components/GlobalProvider/useGlobalProviderLogic.ts +172 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +8 -1
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +26 -3
- package/src/build-components/OnboardButton/pattern.json +5 -3
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +12 -0
- package/src/build-components/OnboardProvider/pattern.json +9 -1
- package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +12 -0
- package/src/build-components/PaywallProvider/pattern.json +9 -1
- package/src/build-components/RenderNode.generated.tsx +10 -0
- package/src/build-components/SystemButton/SystemButton.tsx +6 -0
- package/src/build-components/SystemButton/SystemButtonProps.generated.ts +26 -3
- package/src/build-components/SystemButton/pattern.json +5 -3
- package/src/build-components/SystemButton/usePlacementButtonEvents.ts +51 -27
- package/src/build-components/TermsProvider/TermsProvider.tsx +45 -0
- package/src/build-components/TermsProvider/TermsProviderProps.generated.ts +82 -0
- package/src/build-components/TermsProvider/pattern.json +35 -0
- package/src/build-components/index.ts +10 -0
- package/src/build-components/patterns.generated.ts +2290 -1399
- package/src/components/AttributesEditorPanel.tsx +1 -0
- package/src/modals/CreateDeviceModal.tsx +12 -2
- package/src/modals/DeviceSelectorModal.tsx +1 -1
- package/src/patterns/event-constants.json +19 -0
- package/src/product-base/calculations.ts +30 -1
- package/src/product-base/extractAndroidParams.ts +2 -3
- package/src/product-base/extractIOSParams.ts +4 -4
- package/src/product-base/mockProducts.json +102 -0
- package/src/styles/components/_global-provider.scss +131 -0
- package/src/styles/index.scss +1 -0
- package/src/utils/analyseNodeByPatterns.ts +5 -2
- package/src/utils/nodeTree.ts +115 -0
- package/src/.DS_Store +0 -0
- package/src/assets/.DS_Store +0 -0
|
@@ -31,7 +31,8 @@ export function CreateDeviceModal({
|
|
|
31
31
|
onSuccess,
|
|
32
32
|
deviceToEdit,
|
|
33
33
|
}: CreateDeviceModalProps) {
|
|
34
|
-
const { addCustomDevice, updateCustomDevice } =
|
|
34
|
+
const { addCustomDevice, updateCustomDevice, customDevices } =
|
|
35
|
+
useCustomDeviceStore();
|
|
35
36
|
const {
|
|
36
37
|
register,
|
|
37
38
|
handleSubmit,
|
|
@@ -127,7 +128,16 @@ export function CreateDeviceModal({
|
|
|
127
128
|
<div className="create-device-form__group">
|
|
128
129
|
<label className="create-device-form__label">Device Name</label>
|
|
129
130
|
<input
|
|
130
|
-
{...register('name', {
|
|
131
|
+
{...register('name', {
|
|
132
|
+
required: 'Name is required',
|
|
133
|
+
validate: (value) => {
|
|
134
|
+
if (deviceToEdit && value === deviceToEdit.name) return true;
|
|
135
|
+
const exists = customDevices.some(
|
|
136
|
+
(d) => d.name.toLowerCase() === value.trim().toLowerCase(),
|
|
137
|
+
);
|
|
138
|
+
return exists ? 'A device with this name already exists' : true;
|
|
139
|
+
},
|
|
140
|
+
})}
|
|
131
141
|
className="editor-input"
|
|
132
142
|
placeholder="e.g. My Custom iPhone"
|
|
133
143
|
/>
|
|
@@ -26,7 +26,7 @@ export function DeviceSelectorModal({
|
|
|
26
26
|
favoriteDevices: state.favoriteDevices || [],
|
|
27
27
|
toggleFavoriteDevice: state.toggleFavoriteDevice,
|
|
28
28
|
}));
|
|
29
|
-
const { customDevices
|
|
29
|
+
const { customDevices } = useCustomDeviceStore();
|
|
30
30
|
|
|
31
31
|
const allDevices = useMemo(() => {
|
|
32
32
|
return [...customDevices, ...devices];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Central event constants. Referenced via $ref in pattern.json types blocks. Run 'yarn prebuild' after changes.",
|
|
3
|
+
"eventTypes": ["Permission", "Navigate", "Placement", "SetCondition"],
|
|
4
|
+
"placementKeys": ["terms", "onboard", "paywall", "subscription", "home"],
|
|
5
|
+
"conditionKeys": ["termsAccepted"],
|
|
6
|
+
"permissionTypes": [
|
|
7
|
+
"notification",
|
|
8
|
+
"camera",
|
|
9
|
+
"microphone",
|
|
10
|
+
"location",
|
|
11
|
+
"photos",
|
|
12
|
+
"contacts",
|
|
13
|
+
"att",
|
|
14
|
+
"rating",
|
|
15
|
+
"GDPR"
|
|
16
|
+
],
|
|
17
|
+
"validationTypes": ["required", "email", "url", "min", "max"],
|
|
18
|
+
"formFieldNames": ["email", "firstName", "lastName", "phone", "birthday"]
|
|
19
|
+
}
|
|
@@ -12,7 +12,36 @@ export function extractPrice(formattedPrice: string): string {
|
|
|
12
12
|
if (!formattedPrice) {
|
|
13
13
|
return '';
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
// Remove currency symbols and other non-numeric chars except dot/comma
|
|
16
|
+
const cleaned = formattedPrice.replace(/[^0-9.,]/g, '');
|
|
17
|
+
|
|
18
|
+
// If there's both a dot and a comma, comma is likely decimal (e.g. 1.999,99)
|
|
19
|
+
// If there's multiple dots, dots are likely thousands and comma is decimal (e.g. 1.999,99)
|
|
20
|
+
// If there's only a comma, it's decimal (e.g. 149,99)
|
|
21
|
+
|
|
22
|
+
let numeric: string;
|
|
23
|
+
if (cleaned.includes(',') && cleaned.includes('.')) {
|
|
24
|
+
// Mixed: 1.234,56 -> 1234.56
|
|
25
|
+
numeric = cleaned.replace(/\./g, '').replace(',', '.');
|
|
26
|
+
} else if (cleaned.includes(',')) {
|
|
27
|
+
// Only comma: 149,99 -> 149.99
|
|
28
|
+
numeric = cleaned.replace(',', '.');
|
|
29
|
+
} else {
|
|
30
|
+
// Only dots or none: 1,999.99 (impossible with logic above but for safety) or 9.99
|
|
31
|
+
// If multiple dots, they are thousand separators
|
|
32
|
+
const dots = (cleaned.match(/\./g) || []).length;
|
|
33
|
+
if (dots > 1) {
|
|
34
|
+
numeric = cleaned.replace(/\./g, '');
|
|
35
|
+
} else {
|
|
36
|
+
numeric = cleaned;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const parsed = parseFloat(numeric);
|
|
41
|
+
if (isNaN(parsed)) return '';
|
|
42
|
+
|
|
43
|
+
// Round to 2 decimal places to avoid precision issues like 1999.9900000000002
|
|
44
|
+
return String(Math.round(parsed * 100) / 100);
|
|
16
45
|
}
|
|
17
46
|
|
|
18
47
|
/**
|
|
@@ -195,9 +195,8 @@ export function extractAndroidParams(
|
|
|
195
195
|
|
|
196
196
|
/** Boş params ama mock product price'ları ile birleştirilmiş (fallback) */
|
|
197
197
|
function getFallbackParams(product: Product): AndroidParams {
|
|
198
|
-
const price =
|
|
199
|
-
|
|
200
|
-
'',
|
|
198
|
+
const price = extractPrice(
|
|
199
|
+
String(product.price || product.localizedPrice || ''),
|
|
201
200
|
);
|
|
202
201
|
return {
|
|
203
202
|
...getEmptyParams(),
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
} from './periodLocalizationKeys';
|
|
5
5
|
import { iapLogger } from '../logger';
|
|
6
6
|
import {
|
|
7
|
+
extractPrice,
|
|
7
8
|
calculateDiscount,
|
|
8
9
|
calculatePricePerMonth,
|
|
9
10
|
calculatePricePerYear,
|
|
@@ -56,9 +57,8 @@ export function extractIOSParams(
|
|
|
56
57
|
offerId?: string,
|
|
57
58
|
): IOSParams {
|
|
58
59
|
try {
|
|
59
|
-
const price =
|
|
60
|
-
|
|
61
|
-
'',
|
|
60
|
+
const price = extractPrice(
|
|
61
|
+
String(product.price || product.localizedPrice || ''),
|
|
62
62
|
);
|
|
63
63
|
const currency = product.currency || product.currencyCode || '';
|
|
64
64
|
const localizedPrice = product.localizedPrice || '';
|
|
@@ -120,7 +120,7 @@ export function extractIOSParams(
|
|
|
120
120
|
);
|
|
121
121
|
|
|
122
122
|
if (discount) {
|
|
123
|
-
promoPrice = String(discount.price || '')
|
|
123
|
+
promoPrice = extractPrice(String(discount.price || ''));
|
|
124
124
|
const cycles = discount.numberOfPeriods || 1;
|
|
125
125
|
const unit = convertIOSPeriodUnit(
|
|
126
126
|
discount.subscriptionPeriod || 'MONTH',
|
|
@@ -485,5 +485,107 @@
|
|
|
485
485
|
"subscriptionPeriodUnitIOS": "YEAR",
|
|
486
486
|
"subscriptionPeriodNumberIOS": 1
|
|
487
487
|
}
|
|
488
|
+
],
|
|
489
|
+
"vpn-pro": [
|
|
490
|
+
{
|
|
491
|
+
"productId": "com.vpn111.pro.weekly",
|
|
492
|
+
"title": "Pro Subscription (Weekly)",
|
|
493
|
+
"description": "Pro Subscription (Weekly)",
|
|
494
|
+
"localizedPrice": "₺179,99",
|
|
495
|
+
"price": "179.99",
|
|
496
|
+
"currency": "TRY",
|
|
497
|
+
"type": "subs",
|
|
498
|
+
"subscriptionOffers": [],
|
|
499
|
+
"discounts": [],
|
|
500
|
+
"subscriptionPeriodNumberIOS": 7,
|
|
501
|
+
"subscriptionPeriodUnitIOS": "DAY",
|
|
502
|
+
"isConsumable": false
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
"productId": "com.vpn111.pro.monthly",
|
|
506
|
+
"title": "Pro Subscription (Monthly)",
|
|
507
|
+
"description": "Pro Subscription (Monthly)",
|
|
508
|
+
"localizedPrice": "₺399,99",
|
|
509
|
+
"price": "399.99",
|
|
510
|
+
"currency": "TRY",
|
|
511
|
+
"type": "subs",
|
|
512
|
+
"subscriptionOffers": [],
|
|
513
|
+
"discounts": [],
|
|
514
|
+
"subscriptionPeriodNumberIOS": 1,
|
|
515
|
+
"subscriptionPeriodUnitIOS": "MONTH",
|
|
516
|
+
"isConsumable": false
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
"productId": "com.vpn111.pro.annual",
|
|
520
|
+
"title": "Pro Subscription (Annual)",
|
|
521
|
+
"description": "Pro Subscription (Annual)",
|
|
522
|
+
"localizedPrice": "₺1.999,99",
|
|
523
|
+
"price": "1999.99",
|
|
524
|
+
"currency": "TRY",
|
|
525
|
+
"type": "subs",
|
|
526
|
+
"subscriptionOffers": [
|
|
527
|
+
{
|
|
528
|
+
"numberOfPeriodsIOS": 1,
|
|
529
|
+
"paymentMode": "pay-up-front",
|
|
530
|
+
"type": "promotional",
|
|
531
|
+
"period": { "value": 1, "unit": "year" },
|
|
532
|
+
"id": "one.year.discount.annual.offer",
|
|
533
|
+
"price": 999.99,
|
|
534
|
+
"periodCount": 1,
|
|
535
|
+
"displayPrice": "₺999,99",
|
|
536
|
+
"localizedPriceIOS": "₺999,99",
|
|
537
|
+
"offerId": "one.year.discount.annual.offer",
|
|
538
|
+
"localizedPrice": "₺999,99"
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
"numberOfPeriodsIOS": 1,
|
|
542
|
+
"localizedPriceIOS": "₺149,99",
|
|
543
|
+
"displayPrice": "₺149,99",
|
|
544
|
+
"period": { "value": 1, "unit": "month" },
|
|
545
|
+
"periodCount": 1,
|
|
546
|
+
"id": "one.month.discount.annual.offer",
|
|
547
|
+
"type": "promotional",
|
|
548
|
+
"paymentMode": "pay-up-front",
|
|
549
|
+
"price": 149.99,
|
|
550
|
+
"offerId": "one.month.discount.annual.offer",
|
|
551
|
+
"localizedPrice": "₺149,99"
|
|
552
|
+
}
|
|
553
|
+
],
|
|
554
|
+
"discounts": [
|
|
555
|
+
{
|
|
556
|
+
"paymentMode": "pay-up-front",
|
|
557
|
+
"priceAmount": 999.99,
|
|
558
|
+
"localizedPrice": "₺999,99",
|
|
559
|
+
"type": "promotional",
|
|
560
|
+
"subscriptionPeriod": "YEAR",
|
|
561
|
+
"numberOfPeriods": 1,
|
|
562
|
+
"price": "999.99",
|
|
563
|
+
"identifier": "one.year.discount.annual.offer"
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"numberOfPeriods": 1,
|
|
567
|
+
"priceAmount": 149.99,
|
|
568
|
+
"localizedPrice": "₺149,99",
|
|
569
|
+
"identifier": "one.month.discount.annual.offer",
|
|
570
|
+
"subscriptionPeriod": "MONTH",
|
|
571
|
+
"type": "promotional",
|
|
572
|
+
"paymentMode": "pay-up-front",
|
|
573
|
+
"price": "149.99"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
"numberOfPeriods": 1,
|
|
577
|
+
"type": "promotional",
|
|
578
|
+
"subscriptionPeriod": "YEAR",
|
|
579
|
+
"priceAmount": 999.99,
|
|
580
|
+
"paymentMode": "pay-up-front",
|
|
581
|
+
"price": "999.99",
|
|
582
|
+
"localizedPrice": "₺999,99",
|
|
583
|
+
"identifier": "one.year.50discount.annual.offer"
|
|
584
|
+
}
|
|
585
|
+
],
|
|
586
|
+
"subscriptionPeriodNumberIOS": 1,
|
|
587
|
+
"subscriptionPeriodUnitIOS": "YEAR",
|
|
588
|
+
"isConsumable": false
|
|
589
|
+
}
|
|
488
590
|
]
|
|
489
591
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/* Page transition animations for GlobalProvider (platform-style names). */
|
|
2
|
+
$page-transition-duration: 0.3s;
|
|
3
|
+
$page-transition-easing: cubic-bezier(0.32, 0.72, 0, 1);
|
|
4
|
+
|
|
5
|
+
.global-provider-page {
|
|
6
|
+
flex: 1;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
height: 100%;
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.global-provider-page--none {
|
|
14
|
+
animation: none;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.global-provider-page--default {
|
|
18
|
+
animation: global-provider-fade $page-transition-duration $page-transition-easing;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.global-provider-page--fade {
|
|
22
|
+
animation: global-provider-fade $page-transition-duration $page-transition-easing;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@keyframes global-provider-fade {
|
|
26
|
+
from {
|
|
27
|
+
opacity: 0;
|
|
28
|
+
}
|
|
29
|
+
to {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.global-provider-page--fade_from_bottom {
|
|
35
|
+
animation: global-provider-fade-from-bottom $page-transition-duration $page-transition-easing;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@keyframes global-provider-fade-from-bottom {
|
|
39
|
+
from {
|
|
40
|
+
opacity: 0;
|
|
41
|
+
transform: translateY(24px);
|
|
42
|
+
}
|
|
43
|
+
to {
|
|
44
|
+
opacity: 1;
|
|
45
|
+
transform: translateY(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.global-provider-page--fade_from_right {
|
|
50
|
+
animation: global-provider-fade-from-right $page-transition-duration $page-transition-easing;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@keyframes global-provider-fade-from-right {
|
|
54
|
+
from {
|
|
55
|
+
opacity: 0;
|
|
56
|
+
transform: translateX(24px);
|
|
57
|
+
}
|
|
58
|
+
to {
|
|
59
|
+
opacity: 1;
|
|
60
|
+
transform: translateX(0);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.global-provider-page--reveal_from_bottom {
|
|
65
|
+
animation: global-provider-reveal-from-bottom $page-transition-duration $page-transition-easing;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@keyframes global-provider-reveal-from-bottom {
|
|
69
|
+
from {
|
|
70
|
+
opacity: 0;
|
|
71
|
+
transform: translateY(100%);
|
|
72
|
+
}
|
|
73
|
+
to {
|
|
74
|
+
opacity: 1;
|
|
75
|
+
transform: translateY(0);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.global-provider-page--scale_from_center {
|
|
80
|
+
animation: global-provider-scale-from-center $page-transition-duration $page-transition-easing;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@keyframes global-provider-scale-from-center {
|
|
84
|
+
from {
|
|
85
|
+
opacity: 0;
|
|
86
|
+
transform: scale(0.95);
|
|
87
|
+
}
|
|
88
|
+
to {
|
|
89
|
+
opacity: 1;
|
|
90
|
+
transform: scale(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.global-provider-page--slide_from_right {
|
|
95
|
+
animation: global-provider-slide-from-right $page-transition-duration $page-transition-easing;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@keyframes global-provider-slide-from-right {
|
|
99
|
+
from {
|
|
100
|
+
transform: translateX(100%);
|
|
101
|
+
}
|
|
102
|
+
to {
|
|
103
|
+
transform: translateX(0);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.global-provider-page--slide_from_left {
|
|
108
|
+
animation: global-provider-slide-from-left $page-transition-duration $page-transition-easing;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@keyframes global-provider-slide-from-left {
|
|
112
|
+
from {
|
|
113
|
+
transform: translateX(-100%);
|
|
114
|
+
}
|
|
115
|
+
to {
|
|
116
|
+
transform: translateX(0);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.global-provider-page--slide_from_bottom {
|
|
121
|
+
animation: global-provider-slide-from-bottom $page-transition-duration $page-transition-easing;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@keyframes global-provider-slide-from-bottom {
|
|
125
|
+
from {
|
|
126
|
+
transform: translateY(100%);
|
|
127
|
+
}
|
|
128
|
+
to {
|
|
129
|
+
transform: translateY(0);
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/styles/index.scss
CHANGED
|
@@ -439,12 +439,15 @@ function validateAttributesByPattern(
|
|
|
439
439
|
if (
|
|
440
440
|
attrName === 'title' ||
|
|
441
441
|
attrName === 'description' ||
|
|
442
|
-
attrName === 'testID'
|
|
442
|
+
attrName === 'testID' ||
|
|
443
|
+
attrName === 'animation'
|
|
443
444
|
) {
|
|
444
445
|
const res = validateAttributeValue(
|
|
445
446
|
pattern.pattern.type,
|
|
446
447
|
attrValue,
|
|
447
|
-
attrName === 'testID'
|
|
448
|
+
attrName === 'testID' || attrName === 'animation'
|
|
449
|
+
? 'string'
|
|
450
|
+
: attrName,
|
|
448
451
|
joinPath(path, attrName),
|
|
449
452
|
);
|
|
450
453
|
if (!res.valid) return res;
|
package/src/utils/nodeTree.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Node, NodeData } from '../types/Node';
|
|
2
|
+
import eventConstants from '../patterns/event-constants.json';
|
|
2
3
|
|
|
3
4
|
export function deleteNodeFromTree(root: Node, target: Node): Node {
|
|
4
5
|
if (root === null || root === undefined) return root;
|
|
@@ -97,3 +98,117 @@ export function findNodeByKey(root: Node, key?: string): Node | null {
|
|
|
97
98
|
|
|
98
99
|
return null;
|
|
99
100
|
}
|
|
101
|
+
|
|
102
|
+
export type ProjectOptions = {
|
|
103
|
+
pageKeys: string[];
|
|
104
|
+
conditionKeys: string[];
|
|
105
|
+
placementKeys: string[];
|
|
106
|
+
formFieldNames: string[];
|
|
107
|
+
eventTypes: string[];
|
|
108
|
+
validationTypes: string[];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Traverses the entire node tree to dynamically discover project-level metadata
|
|
113
|
+
* (page keys, condition keys, form field names, etc.) and merges them with
|
|
114
|
+
* central constants from event-constants.json.
|
|
115
|
+
*
|
|
116
|
+
* This enables the Attributes Editor to provide a complete list of valid options
|
|
117
|
+
* for dropdown fields, combining predefined standards with actually used keys
|
|
118
|
+
* in the current design.
|
|
119
|
+
*/
|
|
120
|
+
export function collectProjectMetadata(root: Node): ProjectOptions {
|
|
121
|
+
const pageKeys = new Set<string>();
|
|
122
|
+
const conditionKeys = new Set<string>();
|
|
123
|
+
const placementKeys = new Set<string>();
|
|
124
|
+
const formFieldNames = new Set<string>();
|
|
125
|
+
const eventTypes = new Set<string>();
|
|
126
|
+
|
|
127
|
+
function traverse(node: Node) {
|
|
128
|
+
if (!node || typeof node === 'string') return;
|
|
129
|
+
|
|
130
|
+
if (Array.isArray(node)) {
|
|
131
|
+
node.forEach(traverse);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const data = node as NodeData;
|
|
136
|
+
const type = data.type;
|
|
137
|
+
const attrs = (data.attributes ?? {}) as Record<string, any>;
|
|
138
|
+
|
|
139
|
+
// Collect Page Keys
|
|
140
|
+
if (type === 'GlobalProvider' && Array.isArray(data.children)) {
|
|
141
|
+
data.children.forEach((child) => {
|
|
142
|
+
if (typeof child === 'object' && child !== null && 'key' in child) {
|
|
143
|
+
if (typeof child.key === 'string') pageKeys.add(child.key);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (attrs.pageKey && typeof attrs.pageKey === 'string') {
|
|
148
|
+
pageKeys.add(attrs.pageKey);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Collect Condition Keys
|
|
152
|
+
if (attrs.conditionKey && typeof attrs.conditionKey === 'string') {
|
|
153
|
+
conditionKeys.add(attrs.conditionKey);
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(attrs.skipConditions)) {
|
|
156
|
+
attrs.skipConditions.forEach((entry: any) => {
|
|
157
|
+
if (entry?.conditionKey) conditionKeys.add(entry.conditionKey);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Collect Placement Keys
|
|
162
|
+
if (attrs.placementKey && typeof attrs.placementKey === 'string') {
|
|
163
|
+
placementKeys.add(attrs.placementKey);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Collect Form Field Names
|
|
167
|
+
if (type.startsWith('Form') && type !== 'FormProvider' && attrs.name) {
|
|
168
|
+
if (typeof attrs.name === 'string') formFieldNames.add(attrs.name);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Collect from events
|
|
172
|
+
if (Array.isArray(attrs.events)) {
|
|
173
|
+
attrs.events.forEach((evt: any) => {
|
|
174
|
+
if (evt.type && typeof evt.type === 'string') eventTypes.add(evt.type);
|
|
175
|
+
if (evt.navigate_to) pageKeys.add(evt.navigate_to);
|
|
176
|
+
if (evt.placementKey) placementKeys.add(evt.placementKey);
|
|
177
|
+
if (evt.conditionKey) conditionKeys.add(evt.conditionKey);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (data.children) {
|
|
182
|
+
traverse(data.children as Node);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
traverse(root);
|
|
187
|
+
|
|
188
|
+
// Merge with central constants for a complete set of options
|
|
189
|
+
const result: ProjectOptions = {
|
|
190
|
+
pageKeys: Array.from(
|
|
191
|
+
new Set([...pageKeys, ...eventConstants.placementKeys]),
|
|
192
|
+
).sort(),
|
|
193
|
+
conditionKeys: Array.from(
|
|
194
|
+
new Set([...conditionKeys, ...eventConstants.conditionKeys]),
|
|
195
|
+
).sort(),
|
|
196
|
+
placementKeys: Array.from(
|
|
197
|
+
new Set([...placementKeys, ...eventConstants.placementKeys]),
|
|
198
|
+
).sort(),
|
|
199
|
+
formFieldNames: Array.from(
|
|
200
|
+
new Set([
|
|
201
|
+
...formFieldNames,
|
|
202
|
+
...((eventConstants as any).formFieldNames as string[]),
|
|
203
|
+
]),
|
|
204
|
+
).sort(),
|
|
205
|
+
eventTypes: Array.from(
|
|
206
|
+
new Set([...eventTypes, ...eventConstants.eventTypes]),
|
|
207
|
+
).sort(),
|
|
208
|
+
validationTypes: Array.from(
|
|
209
|
+
new Set((eventConstants as any).validationTypes as string[]),
|
|
210
|
+
).sort(),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
}
|
package/src/.DS_Store
DELETED
|
Binary file
|
package/src/assets/.DS_Store
DELETED
|
Binary file
|