@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.
@@ -1,16 +1,336 @@
1
1
  'use strict';
2
2
 
3
- var fieldcraftProLicense = require('@squaredr/fieldcraft-pro-license');
4
3
  var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
5
  var core = require('@dnd-kit/core');
6
6
  var lucideReact = require('lucide-react');
7
7
  var fieldcraftReact = require('@squaredr/fieldcraft-react');
8
8
  var fieldcraftCore = require('@squaredr/fieldcraft-core');
9
9
  var clsx = require('clsx');
10
10
  var tailwindMerge = require('tailwind-merge');
11
- var jsxRuntime = require('react/jsx-runtime');
12
11
 
13
- // src/form-builder/components/FormBuilderGated.tsx
12
+ // ../license/dist/index.mjs
13
+ var PRO_FEATURES = [
14
+ "SchemaEditor",
15
+ "ResponseViewer",
16
+ "ThemeEditor",
17
+ "FormBuilder",
18
+ "ApiManager",
19
+ "Analytics"
20
+ ];
21
+ var ALL_FEATURES = [
22
+ ...PRO_FEATURES,
23
+ "Telehealth"
24
+ ];
25
+ var TIER_FEATURES = {
26
+ starter: ["SchemaEditor", "ResponseViewer"],
27
+ pro: PRO_FEATURES,
28
+ business: ALL_FEATURES,
29
+ enterprise: ALL_FEATURES
30
+ };
31
+ function tierHasFeature(tier, featureName) {
32
+ return TIER_FEATURES[tier]?.includes(featureName) ?? false;
33
+ }
34
+ var DEV_HOSTNAMES = /* @__PURE__ */ new Set([
35
+ "localhost",
36
+ "127.0.0.1",
37
+ "0.0.0.0",
38
+ "[::1]",
39
+ "::1"
40
+ ]);
41
+ var DEV_HOSTNAME_PATTERNS = [
42
+ /^192\.168\.\d+\.\d+$/,
43
+ // local network
44
+ /^10\.\d+\.\d+\.\d+$/,
45
+ // local network
46
+ /^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/
47
+ // local network
48
+ ];
49
+ var PRODUCTION_HOST_SUFFIXES = [
50
+ ".vercel.app",
51
+ ".netlify.app",
52
+ ".netlify.com",
53
+ ".herokuapp.com",
54
+ ".fly.dev",
55
+ ".railway.app",
56
+ ".render.com",
57
+ ".onrender.com",
58
+ ".pages.dev",
59
+ // Cloudflare Pages
60
+ ".workers.dev",
61
+ // Cloudflare Workers
62
+ ".azurewebsites.net",
63
+ ".web.app",
64
+ // Firebase
65
+ ".firebaseapp.com",
66
+ ".amplifyapp.com",
67
+ ".surge.sh",
68
+ ".github.io",
69
+ ".gitlab.io"
70
+ ];
71
+ function isDevHostname(hostname) {
72
+ if (DEV_HOSTNAMES.has(hostname)) return true;
73
+ for (const pattern of DEV_HOSTNAME_PATTERNS) {
74
+ if (pattern.test(hostname)) return true;
75
+ }
76
+ return false;
77
+ }
78
+ function isKnownProductionHost(hostname) {
79
+ for (const suffix of PRODUCTION_HOST_SUFFIXES) {
80
+ if (hostname.endsWith(suffix)) return true;
81
+ }
82
+ return false;
83
+ }
84
+ function hasRealTLD(hostname) {
85
+ return /\.[a-z]{2,}$/i.test(hostname) && !isDevHostname(hostname);
86
+ }
87
+ function isProductionEnvironment() {
88
+ const _proc = typeof globalThis !== "undefined" ? globalThis.process : void 0;
89
+ if (_proc?.env) {
90
+ const nodeEnv = _proc.env.NODE_ENV;
91
+ if (nodeEnv === "production") return true;
92
+ if (nodeEnv === "development" || nodeEnv === "test") return false;
93
+ }
94
+ if (typeof window !== "undefined" && window.location) {
95
+ const { hostname, protocol, port } = window.location;
96
+ if (protocol === "file:") return false;
97
+ if (isDevHostname(hostname)) return false;
98
+ if (port && port !== "443" && port !== "80") return false;
99
+ if (isKnownProductionHost(hostname)) return true;
100
+ if (protocol === "https:" && hasRealTLD(hostname)) return true;
101
+ if (hasRealTLD(hostname)) return true;
102
+ }
103
+ return false;
104
+ }
105
+ var defaultContext = { status: "validating", tier: null };
106
+ var LicenseCtx = react.createContext(defaultContext);
107
+ function useLicense() {
108
+ return react.useContext(LicenseCtx);
109
+ }
110
+ function UnlicensedOverlay({ featureName, reason, children }) {
111
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
112
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { pointerEvents: "none", userSelect: "none", filter: "blur(2px)" }, children }),
113
+ /* @__PURE__ */ jsxRuntime.jsxs(
114
+ "div",
115
+ {
116
+ style: {
117
+ position: "absolute",
118
+ inset: 0,
119
+ zIndex: 2147483647,
120
+ display: "flex",
121
+ flexDirection: "column",
122
+ alignItems: "center",
123
+ justifyContent: "center",
124
+ backgroundColor: "rgba(0, 0, 0, 0.75)",
125
+ backdropFilter: "blur(4px)",
126
+ fontFamily: "system-ui, -apple-system, sans-serif",
127
+ padding: "32px"
128
+ },
129
+ children: [
130
+ /* @__PURE__ */ jsxRuntime.jsx(
131
+ "div",
132
+ {
133
+ style: {
134
+ position: "absolute",
135
+ inset: 0,
136
+ overflow: "hidden",
137
+ pointerEvents: "none",
138
+ zIndex: 0
139
+ },
140
+ children: Array.from({ length: 12 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
141
+ "div",
142
+ {
143
+ style: {
144
+ position: "absolute",
145
+ top: `${i * 80}px`,
146
+ left: "-50%",
147
+ right: "-50%",
148
+ textAlign: "center",
149
+ transform: "rotate(-30deg)",
150
+ fontSize: "18px",
151
+ fontWeight: 700,
152
+ color: "rgba(255, 255, 255, 0.06)",
153
+ letterSpacing: "8px",
154
+ textTransform: "uppercase",
155
+ whiteSpace: "nowrap",
156
+ userSelect: "none"
157
+ },
158
+ children: "UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO"
159
+ },
160
+ i
161
+ ))
162
+ }
163
+ ),
164
+ /* @__PURE__ */ jsxRuntime.jsxs(
165
+ "div",
166
+ {
167
+ style: {
168
+ position: "relative",
169
+ zIndex: 1,
170
+ textAlign: "center",
171
+ maxWidth: "420px"
172
+ },
173
+ children: [
174
+ /* @__PURE__ */ jsxRuntime.jsx(
175
+ "div",
176
+ {
177
+ style: {
178
+ width: "64px",
179
+ height: "64px",
180
+ margin: "0 auto 16px",
181
+ borderRadius: "50%",
182
+ backgroundColor: "rgba(239, 68, 68, 0.2)",
183
+ border: "2px solid rgba(239, 68, 68, 0.5)",
184
+ display: "flex",
185
+ alignItems: "center",
186
+ justifyContent: "center",
187
+ fontSize: "28px"
188
+ },
189
+ children: "\u{1F6E1}"
190
+ }
191
+ ),
192
+ /* @__PURE__ */ jsxRuntime.jsx(
193
+ "div",
194
+ {
195
+ style: {
196
+ fontSize: "22px",
197
+ fontWeight: 700,
198
+ color: "#ffffff",
199
+ marginBottom: "8px",
200
+ letterSpacing: "-0.02em"
201
+ },
202
+ children: "License Required"
203
+ }
204
+ ),
205
+ /* @__PURE__ */ jsxRuntime.jsx(
206
+ "div",
207
+ {
208
+ style: {
209
+ fontSize: "15px",
210
+ fontWeight: 600,
211
+ color: "#f87171",
212
+ marginBottom: "6px"
213
+ },
214
+ children: featureName
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsxRuntime.jsx(
218
+ "div",
219
+ {
220
+ style: {
221
+ fontSize: "14px",
222
+ color: "#d1d5db",
223
+ marginBottom: "24px",
224
+ lineHeight: "1.5"
225
+ },
226
+ children: reason
227
+ }
228
+ ),
229
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "10px", justifyContent: "center", flexWrap: "wrap" }, children: [
230
+ /* @__PURE__ */ jsxRuntime.jsx(
231
+ "a",
232
+ {
233
+ href: "https://squaredr.tech/products/fieldcraft/admin-pro#pricing",
234
+ target: "_blank",
235
+ rel: "noopener noreferrer",
236
+ style: {
237
+ display: "inline-block",
238
+ padding: "12px 24px",
239
+ fontSize: "14px",
240
+ fontWeight: 600,
241
+ color: "#ffffff",
242
+ backgroundColor: "#2563eb",
243
+ borderRadius: "8px",
244
+ textDecoration: "none",
245
+ boxShadow: "0 4px 14px rgba(37, 99, 235, 0.4)"
246
+ },
247
+ children: "Get a License"
248
+ }
249
+ ),
250
+ /* @__PURE__ */ jsxRuntime.jsx(
251
+ "a",
252
+ {
253
+ href: "https://discord.gg/zMxdu5UVW",
254
+ target: "_blank",
255
+ rel: "noopener noreferrer",
256
+ style: {
257
+ display: "inline-block",
258
+ padding: "12px 24px",
259
+ fontSize: "14px",
260
+ fontWeight: 600,
261
+ color: "#93c5fd",
262
+ backgroundColor: "rgba(37, 99, 235, 0.15)",
263
+ border: "1px solid rgba(37, 99, 235, 0.4)",
264
+ borderRadius: "8px",
265
+ textDecoration: "none"
266
+ },
267
+ children: "Join Discord"
268
+ }
269
+ )
270
+ ] }),
271
+ /* @__PURE__ */ jsxRuntime.jsxs(
272
+ "div",
273
+ {
274
+ style: {
275
+ fontSize: "12px",
276
+ color: "#6b7280",
277
+ marginTop: "16px"
278
+ },
279
+ children: [
280
+ "This component works freely in development.",
281
+ " ",
282
+ /* @__PURE__ */ jsxRuntime.jsx(
283
+ "a",
284
+ {
285
+ href: "https://squaredr.tech/products/fieldcraft/docs/pro/license",
286
+ target: "_blank",
287
+ rel: "noopener noreferrer",
288
+ style: { color: "#9ca3af", textDecoration: "underline" },
289
+ children: "Learn more"
290
+ }
291
+ )
292
+ ]
293
+ }
294
+ )
295
+ ]
296
+ }
297
+ )
298
+ ]
299
+ }
300
+ )
301
+ ] });
302
+ }
303
+ function requireLicense(Component2, featureName) {
304
+ function LicenseGated(props) {
305
+ const { status, tier } = useLicense();
306
+ const isProduction = isProductionEnvironment();
307
+ if (!isProduction) {
308
+ return /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props });
309
+ }
310
+ if (status === "validating") {
311
+ return null;
312
+ }
313
+ const isLicensed = status === "valid" && tier != null && tierHasFeature(tier, featureName);
314
+ if (isLicensed) {
315
+ return /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props });
316
+ }
317
+ let reason = "A valid license is required for production use.";
318
+ if (status === "invalid") {
319
+ reason = "Invalid license key. Please check your license key and try again.";
320
+ } else if (status === "expired") {
321
+ reason = "Your license has expired. Please renew to continue using this component in production.";
322
+ } else if (status === "revoked") {
323
+ reason = "This license key has been revoked. Please contact support or purchase a new license.";
324
+ } else if (status === "domain_mismatch") {
325
+ 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.";
326
+ } else if (!tier || !tierHasFeature(tier, featureName)) {
327
+ reason = "Your license does not include this feature. Please upgrade your plan.";
328
+ }
329
+ return /* @__PURE__ */ jsxRuntime.jsx(UnlicensedOverlay, { featureName, reason, children: /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props }) });
330
+ }
331
+ LicenseGated.displayName = `requireLicense(${Component2.displayName || Component2.name || "Component"})`;
332
+ return LicenseGated;
333
+ }
14
334
  var MAX_HISTORY = 50;
15
335
  function useUndoRedo(currentSchema, setSchema) {
16
336
  const historyRef = react.useRef([currentSchema]);
@@ -3122,7 +3442,7 @@ function FormBuilderInner(props) {
3122
3442
  }
3123
3443
 
3124
3444
  // src/form-builder/components/FormBuilderGated.tsx
3125
- var FormBuilder = fieldcraftProLicense.requireLicense(FormBuilderInner, "FormBuilder");
3445
+ var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
3126
3446
 
3127
3447
  // src/form-builder/theme/presets.ts
3128
3448
  var squaredrDarkPreset = {
@@ -1,2 +1,3 @@
1
- export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from '../chunk-DDQDYTMB.mjs';
1
+ export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from '../chunk-CJBC3KWB.mjs';
2
2
  export { cn } from '../chunk-QQ4JZGTD.mjs';
3
+ import '../chunk-VECQKSWS.mjs';
package/dist/index.d.mts CHANGED
@@ -1,9 +1,58 @@
1
- export { FieldCraftProProvider, LicenseContext, LicenseStatus, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense } from '@squaredr/fieldcraft-pro-license';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType } from 'react';
2
3
  export { BuilderState, BuilderStateHook, DEFAULT_PALETTE, DEFAULT_SCHEMA, DragItem, DropTarget, FormBuilder, FormBuilderProps, FormBuilderTheme, FormBuilderThemeProvider, MutationAction, PaletteCategory, PropertyPanelTab, QUESTION_TYPE_INFO, QuestionTypeCategory, QuestionTypeInfo, SelectedItem, UndoRedoState, addOption, addQuestion, addSection, cleanPreset, cn, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './form-builder/index.mjs';
3
4
  export { ResponseField, ResponseViewer, ResponseViewerProps, ViewMode } from './response-viewer/index.mjs';
4
5
  export { PREVIEW_SCHEMA, ThemeEditor, ThemeEditorInner, ThemeEditorProps } from './theme-editor/index.mjs';
5
- import 'react';
6
6
  import '@squaredr/fieldcraft-core';
7
- import 'react/jsx-runtime';
8
7
  import 'clsx';
9
8
  import '@dnd-kit/core';
9
+
10
+ type LicenseStatus = "validating" | "valid" | "invalid" | "expired" | "revoked" | "domain_mismatch";
11
+ type LicenseTier = "starter" | "pro" | "business" | "enterprise";
12
+ type LicenseContext = {
13
+ status: LicenseStatus;
14
+ tier: LicenseTier | null;
15
+ };
16
+
17
+ type FieldCraftProProviderProps = {
18
+ licenseKey: string;
19
+ children: ReactNode;
20
+ };
21
+ declare function FieldCraftProProvider({ licenseKey, children }: FieldCraftProProviderProps): react_jsx_runtime.JSX.Element;
22
+
23
+ declare function useLicense(): LicenseContext;
24
+
25
+ declare function requireLicense<P extends object>(Component: ComponentType<P>, featureName: string): ComponentType<P>;
26
+
27
+ declare function validateLicense(key: string): Promise<LicenseContext>;
28
+
29
+ type UnlicensedOverlayProps = {
30
+ featureName: string;
31
+ reason: string;
32
+ children: ReactNode;
33
+ };
34
+ /**
35
+ * Renders children (the actual Pro component) with a giant,
36
+ * unmissable overlay on top. The component is visible underneath
37
+ * but completely unusable — forcing a license purchase for production.
38
+ */
39
+ declare function UnlicensedOverlay({ featureName, reason, children }: UnlicensedOverlayProps): react_jsx_runtime.JSX.Element;
40
+
41
+ /**
42
+ * Detects whether the current environment is a production deployment.
43
+ *
44
+ * Dev (returns false) = component works freely, no watermark:
45
+ * - localhost, 127.0.0.1, 0.0.0.0, [::1]
46
+ * - Ports like :3000, :5173, :4200, :8080
47
+ * - NODE_ENV !== "production"
48
+ * - file:// protocol
49
+ *
50
+ * Production (returns true) = watermark overlay:
51
+ * - Real domains (.com, .io, .dev, etc.)
52
+ * - HTTPS protocol
53
+ * - NODE_ENV === "production"
54
+ * - Known hosting platforms (vercel.app, netlify.app, etc.)
55
+ */
56
+ declare function isProductionEnvironment(): boolean;
57
+
58
+ export { FieldCraftProProvider, type LicenseContext, type LicenseStatus, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,58 @@
1
- export { FieldCraftProProvider, LicenseContext, LicenseStatus, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense } from '@squaredr/fieldcraft-pro-license';
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode, ComponentType } from 'react';
2
3
  export { BuilderState, BuilderStateHook, DEFAULT_PALETTE, DEFAULT_SCHEMA, DragItem, DropTarget, FormBuilder, FormBuilderProps, FormBuilderTheme, FormBuilderThemeProvider, MutationAction, PaletteCategory, PropertyPanelTab, QUESTION_TYPE_INFO, QuestionTypeCategory, QuestionTypeInfo, SelectedItem, UndoRedoState, addOption, addQuestion, addSection, cleanPreset, cn, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './form-builder/index.js';
3
4
  export { ResponseField, ResponseViewer, ResponseViewerProps, ViewMode } from './response-viewer/index.js';
4
5
  export { PREVIEW_SCHEMA, ThemeEditor, ThemeEditorInner, ThemeEditorProps } from './theme-editor/index.js';
5
- import 'react';
6
6
  import '@squaredr/fieldcraft-core';
7
- import 'react/jsx-runtime';
8
7
  import 'clsx';
9
8
  import '@dnd-kit/core';
9
+
10
+ type LicenseStatus = "validating" | "valid" | "invalid" | "expired" | "revoked" | "domain_mismatch";
11
+ type LicenseTier = "starter" | "pro" | "business" | "enterprise";
12
+ type LicenseContext = {
13
+ status: LicenseStatus;
14
+ tier: LicenseTier | null;
15
+ };
16
+
17
+ type FieldCraftProProviderProps = {
18
+ licenseKey: string;
19
+ children: ReactNode;
20
+ };
21
+ declare function FieldCraftProProvider({ licenseKey, children }: FieldCraftProProviderProps): react_jsx_runtime.JSX.Element;
22
+
23
+ declare function useLicense(): LicenseContext;
24
+
25
+ declare function requireLicense<P extends object>(Component: ComponentType<P>, featureName: string): ComponentType<P>;
26
+
27
+ declare function validateLicense(key: string): Promise<LicenseContext>;
28
+
29
+ type UnlicensedOverlayProps = {
30
+ featureName: string;
31
+ reason: string;
32
+ children: ReactNode;
33
+ };
34
+ /**
35
+ * Renders children (the actual Pro component) with a giant,
36
+ * unmissable overlay on top. The component is visible underneath
37
+ * but completely unusable — forcing a license purchase for production.
38
+ */
39
+ declare function UnlicensedOverlay({ featureName, reason, children }: UnlicensedOverlayProps): react_jsx_runtime.JSX.Element;
40
+
41
+ /**
42
+ * Detects whether the current environment is a production deployment.
43
+ *
44
+ * Dev (returns false) = component works freely, no watermark:
45
+ * - localhost, 127.0.0.1, 0.0.0.0, [::1]
46
+ * - Ports like :3000, :5173, :4200, :8080
47
+ * - NODE_ENV !== "production"
48
+ * - file:// protocol
49
+ *
50
+ * Production (returns true) = watermark overlay:
51
+ * - Real domains (.com, .io, .dev, etc.)
52
+ * - HTTPS protocol
53
+ * - NODE_ENV === "production"
54
+ * - Known hosting platforms (vercel.app, netlify.app, etc.)
55
+ */
56
+ declare function isProductionEnvironment(): boolean;
57
+
58
+ export { FieldCraftProProvider, type LicenseContext, type LicenseStatus, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense };