@squaredr/fieldcraft-pro 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-MQGR25NG.mjs → chunk-7LQW5QYT.mjs} +1 -3
- package/dist/{chunk-DDQDYTMB.mjs → chunk-CJBC3KWB.mjs} +1 -1
- package/dist/{chunk-LOFGBNJV.mjs → chunk-RSU3X25P.mjs} +1 -1
- package/dist/chunk-VECQKSWS.mjs +582 -0
- package/dist/form-builder/index.js +324 -4
- package/dist/form-builder/index.mjs +2 -1
- package/dist/index.d.mts +52 -3
- package/dist/index.d.ts +52 -3
- package/dist/index.js +587 -30
- package/dist/index.mjs +5 -4
- package/dist/response-viewer/index.js +324 -4
- package/dist/response-viewer/index.mjs +2 -1
- package/dist/theme-editor/index.js +324 -4
- package/dist/theme-editor/index.mjs +2 -1
- package/package.json +3 -3
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { requireLicense } from '
|
|
1
|
+
import { requireLicense } from './chunk-VECQKSWS.mjs';
|
|
2
2
|
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
3
3
|
import { cleanPreset, playfulPreset, clinicalPreset, highContrastPreset, modernPreset, darkPreset, FormEngineRenderer } from '@squaredr/fieldcraft-react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
-
// src/theme-editor/ThemeEditor.tsx
|
|
7
|
-
|
|
8
6
|
// src/theme-editor/preview-schema.ts
|
|
9
7
|
var PREVIEW_SCHEMA = {
|
|
10
8
|
id: "theme-preview",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from './chunk-QQ4JZGTD.mjs';
|
|
2
|
-
import { requireLicense } from '
|
|
2
|
+
import { requireLicense } from './chunk-VECQKSWS.mjs';
|
|
3
3
|
import { forwardRef, createContext, Component, useRef, useEffect, useCallback, useState, useMemo, useContext } from 'react';
|
|
4
4
|
import { DndContext, DragOverlay, useSensors, useSensor, MouseSensor, TouchSensor, useDraggable, useDroppable } from '@dnd-kit/core';
|
|
5
5
|
import { ChevronDown, Undo2, Redo2, Upload, Download, Save, Search, ChevronRight, Plus, Settings, Copy, Trash2, X, HelpCircle, MoveVertical, Minus, Video, Image, FileText, PartyPopper, Hand, ShieldCheck, SeparatorHorizontal, Info, Heading, Trophy, EyeOff, Calculator, CreditCard, MapPin, Repeat, Grid3X3, Camera, PenTool, Paperclip, CalendarCheck, CalendarRange, Clock, Calendar, ArrowUpDown, Globe, ToggleLeft, CheckSquare, CircleDot, ListOrdered, TrendingUp, BarChart3, Star, SlidersHorizontal, Hash, UserCheck, Link, PhoneCall, Phone, Mail, AlignLeft, Type, GripVertical } from 'lucide-react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cn } from './chunk-QQ4JZGTD.mjs';
|
|
2
|
-
import { requireLicense } from '
|
|
2
|
+
import { requireLicense } from './chunk-VECQKSWS.mjs';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { Button, Separator } from '@squaredr/fieldcraft-react';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
import { createContext, useState, useEffect, useContext } from 'react';
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// ../license/dist/index.mjs
|
|
5
|
+
var LEGACY_TIER_MAP = {
|
|
6
|
+
"01": "starter",
|
|
7
|
+
"02": "pro",
|
|
8
|
+
"03": "business",
|
|
9
|
+
"04": "enterprise"
|
|
10
|
+
};
|
|
11
|
+
var TIER_MAP_NUMERIC = {
|
|
12
|
+
1: "starter",
|
|
13
|
+
2: "pro",
|
|
14
|
+
3: "business",
|
|
15
|
+
4: "enterprise"
|
|
16
|
+
};
|
|
17
|
+
var PRO_FEATURES = [
|
|
18
|
+
"SchemaEditor",
|
|
19
|
+
"ResponseViewer",
|
|
20
|
+
"ThemeEditor",
|
|
21
|
+
"FormBuilder",
|
|
22
|
+
"ApiManager",
|
|
23
|
+
"Analytics"
|
|
24
|
+
];
|
|
25
|
+
var ALL_FEATURES = [
|
|
26
|
+
...PRO_FEATURES,
|
|
27
|
+
"Telehealth"
|
|
28
|
+
];
|
|
29
|
+
var TIER_FEATURES = {
|
|
30
|
+
starter: ["SchemaEditor", "ResponseViewer"],
|
|
31
|
+
pro: PRO_FEATURES,
|
|
32
|
+
business: ALL_FEATURES,
|
|
33
|
+
enterprise: ALL_FEATURES
|
|
34
|
+
};
|
|
35
|
+
var HMAC_SECRET = "e50a657813a5ab9563050728a605b9ab58b911d5c1a9f48c6825f379a533ccd7685d11d01937d9f135776a0db3efeefe29b3e5282b27ede8cee93758f94f2d75";
|
|
36
|
+
var B32_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
|
|
37
|
+
function base32hexDecode(str) {
|
|
38
|
+
const upper = str.toUpperCase();
|
|
39
|
+
let bits = 0;
|
|
40
|
+
let value = 0;
|
|
41
|
+
const bytes = [];
|
|
42
|
+
for (let i = 0; i < upper.length; i++) {
|
|
43
|
+
const idx = B32_CHARS.indexOf(upper[i]);
|
|
44
|
+
if (idx === -1) return null;
|
|
45
|
+
value = value << 5 | idx;
|
|
46
|
+
bits += 5;
|
|
47
|
+
if (bits >= 8) {
|
|
48
|
+
bits -= 8;
|
|
49
|
+
bytes.push(value >>> bits & 255);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return new Uint8Array(bytes);
|
|
53
|
+
}
|
|
54
|
+
function parseLegacyKey(key) {
|
|
55
|
+
const parts = key.split("-");
|
|
56
|
+
if (parts.length !== 5) return null;
|
|
57
|
+
const [p1, p2, tierHex, expiryHex, hash] = parts;
|
|
58
|
+
if (p1 !== "FC" || p2 !== "PRO") return null;
|
|
59
|
+
if (!(tierHex in LEGACY_TIER_MAP)) return null;
|
|
60
|
+
if (!/^[0-9A-Fa-f]{8}$/.test(expiryHex)) return null;
|
|
61
|
+
if (!/^[0-9A-Fa-f]{8}$/.test(hash)) return null;
|
|
62
|
+
return { format: "legacy", tierHex, expiryHex, hash };
|
|
63
|
+
}
|
|
64
|
+
function parseOpaqueKey(key) {
|
|
65
|
+
const stripped = key.replace(/-/g, "");
|
|
66
|
+
if (!stripped.startsWith("FCPRO")) return null;
|
|
67
|
+
const encoded = stripped.slice(5);
|
|
68
|
+
const decoded = base32hexDecode(encoded);
|
|
69
|
+
if (!decoded || decoded.length < 17) return null;
|
|
70
|
+
const tier = decoded[0];
|
|
71
|
+
if (!(tier in TIER_MAP_NUMERIC)) return null;
|
|
72
|
+
const expiryTimestamp = decoded[1] << 24 | decoded[2] << 16 | decoded[3] << 8 | decoded[4];
|
|
73
|
+
const expiryUnsigned = expiryTimestamp >>> 0;
|
|
74
|
+
const nonce = decoded.slice(5, 9);
|
|
75
|
+
const signature = decoded.slice(9, 17);
|
|
76
|
+
return { format: "opaque", tier, expiryTimestamp: expiryUnsigned, nonce, signature };
|
|
77
|
+
}
|
|
78
|
+
function parseKey(key) {
|
|
79
|
+
if (!key || typeof key !== "string") return null;
|
|
80
|
+
if (key.startsWith("FCPRO-")) {
|
|
81
|
+
return parseOpaqueKey(key);
|
|
82
|
+
}
|
|
83
|
+
return parseLegacyKey(key);
|
|
84
|
+
}
|
|
85
|
+
async function computeHmacLegacy(tierHex, expiryHex) {
|
|
86
|
+
const encoder = new TextEncoder();
|
|
87
|
+
const keyData = encoder.encode(HMAC_SECRET);
|
|
88
|
+
const message = encoder.encode(`FC-PRO-${tierHex}-${expiryHex}`);
|
|
89
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
90
|
+
"raw",
|
|
91
|
+
keyData,
|
|
92
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
93
|
+
false,
|
|
94
|
+
["sign"]
|
|
95
|
+
);
|
|
96
|
+
const signature = await crypto.subtle.sign("HMAC", cryptoKey, message);
|
|
97
|
+
const hashBytes = new Uint8Array(signature).slice(0, 4);
|
|
98
|
+
return Array.from(hashBytes).map((b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
99
|
+
}
|
|
100
|
+
async function computeHmacOpaque(payload) {
|
|
101
|
+
const encoder = new TextEncoder();
|
|
102
|
+
const keyData = encoder.encode(HMAC_SECRET);
|
|
103
|
+
const cryptoKey = await crypto.subtle.importKey(
|
|
104
|
+
"raw",
|
|
105
|
+
keyData,
|
|
106
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
107
|
+
false,
|
|
108
|
+
["sign"]
|
|
109
|
+
);
|
|
110
|
+
const signature = await crypto.subtle.sign("HMAC", cryptoKey, payload);
|
|
111
|
+
return new Uint8Array(signature).slice(0, 8);
|
|
112
|
+
}
|
|
113
|
+
function isExpiredLegacy(expiryHex) {
|
|
114
|
+
const expiryTimestamp = parseInt(expiryHex, 16);
|
|
115
|
+
if (expiryTimestamp === 4294967295) return false;
|
|
116
|
+
return Date.now() / 1e3 > expiryTimestamp;
|
|
117
|
+
}
|
|
118
|
+
function isExpiredOpaque(expiryTimestamp) {
|
|
119
|
+
if (expiryTimestamp === 4294967295) return false;
|
|
120
|
+
return Date.now() / 1e3 > expiryTimestamp;
|
|
121
|
+
}
|
|
122
|
+
async function validateLicense(key) {
|
|
123
|
+
if (!key || typeof key !== "string") {
|
|
124
|
+
return { status: "invalid", tier: null };
|
|
125
|
+
}
|
|
126
|
+
const parsed = parseKey(key);
|
|
127
|
+
if (!parsed) {
|
|
128
|
+
return { status: "invalid", tier: null };
|
|
129
|
+
}
|
|
130
|
+
if (parsed.format === "opaque") {
|
|
131
|
+
const payload = new Uint8Array(9);
|
|
132
|
+
payload[0] = parsed.tier;
|
|
133
|
+
payload[1] = parsed.expiryTimestamp >>> 24 & 255;
|
|
134
|
+
payload[2] = parsed.expiryTimestamp >>> 16 & 255;
|
|
135
|
+
payload[3] = parsed.expiryTimestamp >>> 8 & 255;
|
|
136
|
+
payload[4] = parsed.expiryTimestamp & 255;
|
|
137
|
+
payload.set(parsed.nonce, 5);
|
|
138
|
+
const expectedSig = await computeHmacOpaque(payload);
|
|
139
|
+
let match = true;
|
|
140
|
+
for (let i = 0; i < 8; i++) {
|
|
141
|
+
if (parsed.signature[i] !== expectedSig[i]) {
|
|
142
|
+
match = false;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!match) {
|
|
147
|
+
return { status: "invalid", tier: null };
|
|
148
|
+
}
|
|
149
|
+
const tier2 = TIER_MAP_NUMERIC[parsed.tier];
|
|
150
|
+
if (!tier2) {
|
|
151
|
+
return { status: "invalid", tier: null };
|
|
152
|
+
}
|
|
153
|
+
if (isExpiredOpaque(parsed.expiryTimestamp)) {
|
|
154
|
+
return { status: "expired", tier: tier2 };
|
|
155
|
+
}
|
|
156
|
+
return { status: "valid", tier: tier2 };
|
|
157
|
+
}
|
|
158
|
+
const expectedHash = await computeHmacLegacy(parsed.tierHex, parsed.expiryHex);
|
|
159
|
+
if (parsed.hash.toUpperCase() !== expectedHash) {
|
|
160
|
+
return { status: "invalid", tier: null };
|
|
161
|
+
}
|
|
162
|
+
const tier = LEGACY_TIER_MAP[parsed.tierHex];
|
|
163
|
+
if (isExpiredLegacy(parsed.expiryHex)) {
|
|
164
|
+
return { status: "expired", tier };
|
|
165
|
+
}
|
|
166
|
+
return { status: "valid", tier };
|
|
167
|
+
}
|
|
168
|
+
function tierHasFeature(tier, featureName) {
|
|
169
|
+
return TIER_FEATURES[tier]?.includes(featureName) ?? false;
|
|
170
|
+
}
|
|
171
|
+
var DEV_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
172
|
+
"localhost",
|
|
173
|
+
"127.0.0.1",
|
|
174
|
+
"0.0.0.0",
|
|
175
|
+
"[::1]",
|
|
176
|
+
"::1"
|
|
177
|
+
]);
|
|
178
|
+
var DEV_HOSTNAME_PATTERNS = [
|
|
179
|
+
/^192\.168\.\d+\.\d+$/,
|
|
180
|
+
// local network
|
|
181
|
+
/^10\.\d+\.\d+\.\d+$/,
|
|
182
|
+
// local network
|
|
183
|
+
/^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/
|
|
184
|
+
// local network
|
|
185
|
+
];
|
|
186
|
+
var PRODUCTION_HOST_SUFFIXES = [
|
|
187
|
+
".vercel.app",
|
|
188
|
+
".netlify.app",
|
|
189
|
+
".netlify.com",
|
|
190
|
+
".herokuapp.com",
|
|
191
|
+
".fly.dev",
|
|
192
|
+
".railway.app",
|
|
193
|
+
".render.com",
|
|
194
|
+
".onrender.com",
|
|
195
|
+
".pages.dev",
|
|
196
|
+
// Cloudflare Pages
|
|
197
|
+
".workers.dev",
|
|
198
|
+
// Cloudflare Workers
|
|
199
|
+
".azurewebsites.net",
|
|
200
|
+
".web.app",
|
|
201
|
+
// Firebase
|
|
202
|
+
".firebaseapp.com",
|
|
203
|
+
".amplifyapp.com",
|
|
204
|
+
".surge.sh",
|
|
205
|
+
".github.io",
|
|
206
|
+
".gitlab.io"
|
|
207
|
+
];
|
|
208
|
+
function isDevHostname(hostname) {
|
|
209
|
+
if (DEV_HOSTNAMES.has(hostname)) return true;
|
|
210
|
+
for (const pattern of DEV_HOSTNAME_PATTERNS) {
|
|
211
|
+
if (pattern.test(hostname)) return true;
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
function isKnownProductionHost(hostname) {
|
|
216
|
+
for (const suffix of PRODUCTION_HOST_SUFFIXES) {
|
|
217
|
+
if (hostname.endsWith(suffix)) return true;
|
|
218
|
+
}
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
function hasRealTLD(hostname) {
|
|
222
|
+
return /\.[a-z]{2,}$/i.test(hostname) && !isDevHostname(hostname);
|
|
223
|
+
}
|
|
224
|
+
function isProductionEnvironment() {
|
|
225
|
+
const _proc = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
226
|
+
if (_proc?.env) {
|
|
227
|
+
const nodeEnv = _proc.env.NODE_ENV;
|
|
228
|
+
if (nodeEnv === "production") return true;
|
|
229
|
+
if (nodeEnv === "development" || nodeEnv === "test") return false;
|
|
230
|
+
}
|
|
231
|
+
if (typeof window !== "undefined" && window.location) {
|
|
232
|
+
const { hostname, protocol, port } = window.location;
|
|
233
|
+
if (protocol === "file:") return false;
|
|
234
|
+
if (isDevHostname(hostname)) return false;
|
|
235
|
+
if (port && port !== "443" && port !== "80") return false;
|
|
236
|
+
if (isKnownProductionHost(hostname)) return true;
|
|
237
|
+
if (protocol === "https:" && hasRealTLD(hostname)) return true;
|
|
238
|
+
if (hasRealTLD(hostname)) return true;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
var PING_URL = "https://squaredr.tech/api/license/ping";
|
|
243
|
+
var CACHE_KEY = "fcpro_lp";
|
|
244
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
245
|
+
function hashKey(key) {
|
|
246
|
+
let hash = 0;
|
|
247
|
+
for (let i = 0; i < key.length; i++) {
|
|
248
|
+
hash = (hash << 5) - hash + key.charCodeAt(i) | 0;
|
|
249
|
+
}
|
|
250
|
+
return Math.abs(hash).toString(36);
|
|
251
|
+
}
|
|
252
|
+
function cacheId(key) {
|
|
253
|
+
return `${CACHE_KEY}_${hashKey(key)}`;
|
|
254
|
+
}
|
|
255
|
+
function readCache(key) {
|
|
256
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
257
|
+
try {
|
|
258
|
+
const raw = localStorage.getItem(cacheId(key));
|
|
259
|
+
if (!raw) return null;
|
|
260
|
+
const entry = JSON.parse(raw);
|
|
261
|
+
if (Date.now() - entry.ts > CACHE_TTL_MS) {
|
|
262
|
+
localStorage.removeItem(cacheId(key));
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
return entry;
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function writeCache(key, status, tier, reason = null) {
|
|
271
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
272
|
+
try {
|
|
273
|
+
const entry = { s: status, t: tier, r: reason, ts: Date.now() };
|
|
274
|
+
localStorage.setItem(cacheId(key), JSON.stringify(entry));
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
function getCachedPingResult(key) {
|
|
279
|
+
const cached = readCache(key);
|
|
280
|
+
if (!cached) return null;
|
|
281
|
+
return { status: cached.s, tier: cached.t, reason: cached.r || void 0 };
|
|
282
|
+
}
|
|
283
|
+
async function performPing(key) {
|
|
284
|
+
const cached = readCache(key);
|
|
285
|
+
if (cached) {
|
|
286
|
+
return { status: cached.s, tier: cached.t };
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const controller = new AbortController();
|
|
290
|
+
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
291
|
+
const res = await fetch(PING_URL, {
|
|
292
|
+
method: "POST",
|
|
293
|
+
headers: { "Content-Type": "application/json" },
|
|
294
|
+
body: JSON.stringify({ key }),
|
|
295
|
+
signal: controller.signal
|
|
296
|
+
});
|
|
297
|
+
clearTimeout(timeout);
|
|
298
|
+
if (!res.ok) return null;
|
|
299
|
+
const data = await res.json();
|
|
300
|
+
const tier = data.tier || null;
|
|
301
|
+
if (data.status === "active") {
|
|
302
|
+
writeCache(key, "valid", tier);
|
|
303
|
+
return { status: "valid", tier };
|
|
304
|
+
}
|
|
305
|
+
if (data.status === "revoked") {
|
|
306
|
+
writeCache(key, "revoked", null, data.reason);
|
|
307
|
+
return { status: "revoked", tier: null, reason: data.reason };
|
|
308
|
+
}
|
|
309
|
+
if (data.status === "expired") {
|
|
310
|
+
writeCache(key, "expired", tier);
|
|
311
|
+
return { status: "expired", tier };
|
|
312
|
+
}
|
|
313
|
+
if (data.status === "domain_mismatch") {
|
|
314
|
+
writeCache(key, "domain_mismatch", null, data.reason);
|
|
315
|
+
return { status: "domain_mismatch", tier: null, reason: data.reason };
|
|
316
|
+
}
|
|
317
|
+
return null;
|
|
318
|
+
} catch {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
var defaultContext = { status: "validating", tier: null };
|
|
323
|
+
var LicenseCtx = createContext(defaultContext);
|
|
324
|
+
function FieldCraftProProvider({ licenseKey, children }) {
|
|
325
|
+
const [license, setLicense] = useState(defaultContext);
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
let cancelled = false;
|
|
328
|
+
setLicense(defaultContext);
|
|
329
|
+
validateLicense(licenseKey).then((clientResult) => {
|
|
330
|
+
if (cancelled) return;
|
|
331
|
+
setLicense(clientResult);
|
|
332
|
+
if (clientResult.status !== "valid" || !isProductionEnvironment()) return;
|
|
333
|
+
const cached = getCachedPingResult(licenseKey);
|
|
334
|
+
if (cached) {
|
|
335
|
+
if (cached.status === "revoked" || cached.status === "domain_mismatch") {
|
|
336
|
+
setLicense({ status: cached.status, tier: null });
|
|
337
|
+
}
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
performPing(licenseKey).then((pingResult) => {
|
|
341
|
+
if (cancelled) return;
|
|
342
|
+
if (!pingResult) return;
|
|
343
|
+
if (pingResult.status === "revoked" || pingResult.status === "domain_mismatch") {
|
|
344
|
+
setLicense({ status: pingResult.status, tier: null });
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
return () => {
|
|
349
|
+
cancelled = true;
|
|
350
|
+
};
|
|
351
|
+
}, [licenseKey]);
|
|
352
|
+
return /* @__PURE__ */ jsx(LicenseCtx.Provider, { value: license, children });
|
|
353
|
+
}
|
|
354
|
+
function useLicense() {
|
|
355
|
+
return useContext(LicenseCtx);
|
|
356
|
+
}
|
|
357
|
+
function UnlicensedOverlay({ featureName, reason, children }) {
|
|
358
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
|
|
359
|
+
/* @__PURE__ */ jsx("div", { style: { pointerEvents: "none", userSelect: "none", filter: "blur(2px)" }, children }),
|
|
360
|
+
/* @__PURE__ */ jsxs(
|
|
361
|
+
"div",
|
|
362
|
+
{
|
|
363
|
+
style: {
|
|
364
|
+
position: "absolute",
|
|
365
|
+
inset: 0,
|
|
366
|
+
zIndex: 2147483647,
|
|
367
|
+
display: "flex",
|
|
368
|
+
flexDirection: "column",
|
|
369
|
+
alignItems: "center",
|
|
370
|
+
justifyContent: "center",
|
|
371
|
+
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
372
|
+
backdropFilter: "blur(4px)",
|
|
373
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
374
|
+
padding: "32px"
|
|
375
|
+
},
|
|
376
|
+
children: [
|
|
377
|
+
/* @__PURE__ */ jsx(
|
|
378
|
+
"div",
|
|
379
|
+
{
|
|
380
|
+
style: {
|
|
381
|
+
position: "absolute",
|
|
382
|
+
inset: 0,
|
|
383
|
+
overflow: "hidden",
|
|
384
|
+
pointerEvents: "none",
|
|
385
|
+
zIndex: 0
|
|
386
|
+
},
|
|
387
|
+
children: Array.from({ length: 12 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
388
|
+
"div",
|
|
389
|
+
{
|
|
390
|
+
style: {
|
|
391
|
+
position: "absolute",
|
|
392
|
+
top: `${i * 80}px`,
|
|
393
|
+
left: "-50%",
|
|
394
|
+
right: "-50%",
|
|
395
|
+
textAlign: "center",
|
|
396
|
+
transform: "rotate(-30deg)",
|
|
397
|
+
fontSize: "18px",
|
|
398
|
+
fontWeight: 700,
|
|
399
|
+
color: "rgba(255, 255, 255, 0.06)",
|
|
400
|
+
letterSpacing: "8px",
|
|
401
|
+
textTransform: "uppercase",
|
|
402
|
+
whiteSpace: "nowrap",
|
|
403
|
+
userSelect: "none"
|
|
404
|
+
},
|
|
405
|
+
children: "UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO"
|
|
406
|
+
},
|
|
407
|
+
i
|
|
408
|
+
))
|
|
409
|
+
}
|
|
410
|
+
),
|
|
411
|
+
/* @__PURE__ */ jsxs(
|
|
412
|
+
"div",
|
|
413
|
+
{
|
|
414
|
+
style: {
|
|
415
|
+
position: "relative",
|
|
416
|
+
zIndex: 1,
|
|
417
|
+
textAlign: "center",
|
|
418
|
+
maxWidth: "420px"
|
|
419
|
+
},
|
|
420
|
+
children: [
|
|
421
|
+
/* @__PURE__ */ jsx(
|
|
422
|
+
"div",
|
|
423
|
+
{
|
|
424
|
+
style: {
|
|
425
|
+
width: "64px",
|
|
426
|
+
height: "64px",
|
|
427
|
+
margin: "0 auto 16px",
|
|
428
|
+
borderRadius: "50%",
|
|
429
|
+
backgroundColor: "rgba(239, 68, 68, 0.2)",
|
|
430
|
+
border: "2px solid rgba(239, 68, 68, 0.5)",
|
|
431
|
+
display: "flex",
|
|
432
|
+
alignItems: "center",
|
|
433
|
+
justifyContent: "center",
|
|
434
|
+
fontSize: "28px"
|
|
435
|
+
},
|
|
436
|
+
children: "\u{1F6E1}"
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
/* @__PURE__ */ jsx(
|
|
440
|
+
"div",
|
|
441
|
+
{
|
|
442
|
+
style: {
|
|
443
|
+
fontSize: "22px",
|
|
444
|
+
fontWeight: 700,
|
|
445
|
+
color: "#ffffff",
|
|
446
|
+
marginBottom: "8px",
|
|
447
|
+
letterSpacing: "-0.02em"
|
|
448
|
+
},
|
|
449
|
+
children: "License Required"
|
|
450
|
+
}
|
|
451
|
+
),
|
|
452
|
+
/* @__PURE__ */ jsx(
|
|
453
|
+
"div",
|
|
454
|
+
{
|
|
455
|
+
style: {
|
|
456
|
+
fontSize: "15px",
|
|
457
|
+
fontWeight: 600,
|
|
458
|
+
color: "#f87171",
|
|
459
|
+
marginBottom: "6px"
|
|
460
|
+
},
|
|
461
|
+
children: featureName
|
|
462
|
+
}
|
|
463
|
+
),
|
|
464
|
+
/* @__PURE__ */ jsx(
|
|
465
|
+
"div",
|
|
466
|
+
{
|
|
467
|
+
style: {
|
|
468
|
+
fontSize: "14px",
|
|
469
|
+
color: "#d1d5db",
|
|
470
|
+
marginBottom: "24px",
|
|
471
|
+
lineHeight: "1.5"
|
|
472
|
+
},
|
|
473
|
+
children: reason
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px", justifyContent: "center", flexWrap: "wrap" }, children: [
|
|
477
|
+
/* @__PURE__ */ jsx(
|
|
478
|
+
"a",
|
|
479
|
+
{
|
|
480
|
+
href: "https://squaredr.tech/products/fieldcraft/admin-pro#pricing",
|
|
481
|
+
target: "_blank",
|
|
482
|
+
rel: "noopener noreferrer",
|
|
483
|
+
style: {
|
|
484
|
+
display: "inline-block",
|
|
485
|
+
padding: "12px 24px",
|
|
486
|
+
fontSize: "14px",
|
|
487
|
+
fontWeight: 600,
|
|
488
|
+
color: "#ffffff",
|
|
489
|
+
backgroundColor: "#2563eb",
|
|
490
|
+
borderRadius: "8px",
|
|
491
|
+
textDecoration: "none",
|
|
492
|
+
boxShadow: "0 4px 14px rgba(37, 99, 235, 0.4)"
|
|
493
|
+
},
|
|
494
|
+
children: "Get a License"
|
|
495
|
+
}
|
|
496
|
+
),
|
|
497
|
+
/* @__PURE__ */ jsx(
|
|
498
|
+
"a",
|
|
499
|
+
{
|
|
500
|
+
href: "https://discord.gg/zMxdu5UVW",
|
|
501
|
+
target: "_blank",
|
|
502
|
+
rel: "noopener noreferrer",
|
|
503
|
+
style: {
|
|
504
|
+
display: "inline-block",
|
|
505
|
+
padding: "12px 24px",
|
|
506
|
+
fontSize: "14px",
|
|
507
|
+
fontWeight: 600,
|
|
508
|
+
color: "#93c5fd",
|
|
509
|
+
backgroundColor: "rgba(37, 99, 235, 0.15)",
|
|
510
|
+
border: "1px solid rgba(37, 99, 235, 0.4)",
|
|
511
|
+
borderRadius: "8px",
|
|
512
|
+
textDecoration: "none"
|
|
513
|
+
},
|
|
514
|
+
children: "Join Discord"
|
|
515
|
+
}
|
|
516
|
+
)
|
|
517
|
+
] }),
|
|
518
|
+
/* @__PURE__ */ jsxs(
|
|
519
|
+
"div",
|
|
520
|
+
{
|
|
521
|
+
style: {
|
|
522
|
+
fontSize: "12px",
|
|
523
|
+
color: "#6b7280",
|
|
524
|
+
marginTop: "16px"
|
|
525
|
+
},
|
|
526
|
+
children: [
|
|
527
|
+
"This component works freely in development.",
|
|
528
|
+
" ",
|
|
529
|
+
/* @__PURE__ */ jsx(
|
|
530
|
+
"a",
|
|
531
|
+
{
|
|
532
|
+
href: "https://squaredr.tech/products/fieldcraft/docs/pro/license",
|
|
533
|
+
target: "_blank",
|
|
534
|
+
rel: "noopener noreferrer",
|
|
535
|
+
style: { color: "#9ca3af", textDecoration: "underline" },
|
|
536
|
+
children: "Learn more"
|
|
537
|
+
}
|
|
538
|
+
)
|
|
539
|
+
]
|
|
540
|
+
}
|
|
541
|
+
)
|
|
542
|
+
]
|
|
543
|
+
}
|
|
544
|
+
)
|
|
545
|
+
]
|
|
546
|
+
}
|
|
547
|
+
)
|
|
548
|
+
] });
|
|
549
|
+
}
|
|
550
|
+
function requireLicense(Component, featureName) {
|
|
551
|
+
function LicenseGated(props) {
|
|
552
|
+
const { status, tier } = useLicense();
|
|
553
|
+
const isProduction = isProductionEnvironment();
|
|
554
|
+
if (!isProduction) {
|
|
555
|
+
return /* @__PURE__ */ jsx(Component, { ...props });
|
|
556
|
+
}
|
|
557
|
+
if (status === "validating") {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
const isLicensed = status === "valid" && tier != null && tierHasFeature(tier, featureName);
|
|
561
|
+
if (isLicensed) {
|
|
562
|
+
return /* @__PURE__ */ jsx(Component, { ...props });
|
|
563
|
+
}
|
|
564
|
+
let reason = "A valid license is required for production use.";
|
|
565
|
+
if (status === "invalid") {
|
|
566
|
+
reason = "Invalid license key. Please check your license key and try again.";
|
|
567
|
+
} else if (status === "expired") {
|
|
568
|
+
reason = "Your license has expired. Please renew to continue using this component in production.";
|
|
569
|
+
} else if (status === "revoked") {
|
|
570
|
+
reason = "This license key has been revoked. Please contact support or purchase a new license.";
|
|
571
|
+
} else if (status === "domain_mismatch") {
|
|
572
|
+
reason = "This license key is registered to a different domain. Each key can only be used on one production domain. Please purchase a new license for this domain.";
|
|
573
|
+
} else if (!tier || !tierHasFeature(tier, featureName)) {
|
|
574
|
+
reason = "Your license does not include this feature. Please upgrade your plan.";
|
|
575
|
+
}
|
|
576
|
+
return /* @__PURE__ */ jsx(UnlicensedOverlay, { featureName, reason, children: /* @__PURE__ */ jsx(Component, { ...props }) });
|
|
577
|
+
}
|
|
578
|
+
LicenseGated.displayName = `requireLicense(${Component.displayName || Component.name || "Component"})`;
|
|
579
|
+
return LicenseGated;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export { FieldCraftProProvider, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense };
|