@svgrid/enterprise 1.2.0 → 2.0.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/cdn/svgrid-enterprise.svelte-external.js +26039 -805
- package/dist/designer/assets/index-Dp44bTid.js +939 -0
- package/dist/designer/assets/index-RJp6x8tw.css +1 -0
- package/dist/designer/assets/jszip.min-CjMo-QGg.js +2 -0
- package/dist/designer/index.html +13 -0
- package/dist/node/studio.js +22554 -0
- package/package.json +10 -3
- package/src/SvAuthGate.svelte +115 -0
- package/src/SvBoard.dom.test.ts +67 -0
- package/src/SvBoard.svelte +192 -0
- package/src/SvExportMenu.svelte +553 -0
- package/src/SvFileInput.svelte +113 -0
- package/src/SvGridEditPanel.dom.test.ts +146 -0
- package/src/SvGridEditPanel.svelte +793 -0
- package/src/SvGridMasterDetail.svelte +95 -0
- package/src/SvImportDialog.svelte +1020 -0
- package/src/SvLookupInput.svelte +180 -0
- package/src/SvRecordDetail.dom.test.ts +137 -0
- package/src/SvRecordDetail.svelte +288 -0
- package/src/SvSchedule.dom.test.ts +57 -0
- package/src/SvSchedule.svelte +156 -0
- package/src/SvSchemaChart.svelte +233 -0
- package/src/SvSchemaDashboard.svelte +130 -0
- package/src/ai-export-pdf.test.ts +74 -0
- package/src/ai-export-xlsx.test.ts +87 -0
- package/src/ai-export.test.ts +110 -0
- package/src/ai.ts +1188 -782
- package/src/edit-panel.test.ts +213 -0
- package/src/edit-panel.ts +228 -0
- package/src/export-conditional.test.ts +60 -0
- package/src/export-conditional.ts +94 -0
- package/src/export-ooxml.test.ts +152 -0
- package/src/export-ooxml.ts +485 -0
- package/src/export-pdf.test.ts +138 -0
- package/src/export-pdf.ts +245 -0
- package/src/export-print.test.ts +66 -0
- package/src/export-print.ts +132 -0
- package/src/export-serialize.test.ts +56 -0
- package/src/export-serialize.ts +24 -0
- package/src/export-xls.ts +196 -0
- package/src/export-xlsx-roundtrip.test.ts +120 -0
- package/src/export-xlsx.test.ts +150 -0
- package/src/export.test.ts +349 -0
- package/src/export.ts +1452 -549
- package/src/import-automap.test.ts +131 -0
- package/src/import-hardening.test.ts +158 -0
- package/src/import.ts +1042 -648
- package/src/index.ts +282 -0
- package/src/install.ts +134 -114
- package/src/license-core.test.ts +23 -0
- package/src/license-core.ts +35 -0
- package/src/license.ts +103 -90
- package/src/master-detail.test.ts +61 -0
- package/src/master-detail.ts +42 -0
- package/src/print.ts +107 -127
- package/src/schema-designer.test.ts +121 -0
- package/src/schema-designer.ts +142 -0
- package/src/schema.test.ts +268 -0
- package/src/schema.ts +499 -0
- package/src/smart-shim.ts +107 -105
- package/src/sources/aggregate.test.ts +79 -0
- package/src/sources/aggregate.ts +102 -0
- package/src/sources/auth-supabase.test.ts +80 -0
- package/src/sources/auth-supabase.ts +87 -0
- package/src/sources/dashboard.kpi.test.ts +50 -0
- package/src/sources/dashboard.test.ts +61 -0
- package/src/sources/dashboard.ts +136 -0
- package/src/sources/field-inference.test.ts +60 -0
- package/src/sources/field-inference.ts +63 -0
- package/src/sources/filters.test.ts +58 -0
- package/src/sources/filters.ts +64 -0
- package/src/sources/index.ts +67 -0
- package/src/sources/introspect-supabase.test.ts +100 -0
- package/src/sources/introspect-supabase.ts +119 -0
- package/src/sources/realtime-supabase.test.ts +93 -0
- package/src/sources/realtime-supabase.ts +99 -0
- package/src/sources/relation-lookup.test.ts +99 -0
- package/src/sources/relation-lookup.ts +128 -0
- package/src/sources/rest-adapters.test.ts +95 -0
- package/src/sources/rest-adapters.ts +120 -0
- package/src/sources/rest.test.ts +104 -0
- package/src/sources/rest.ts +129 -0
- package/src/sources/schema-from-columns.test.ts +106 -0
- package/src/sources/schema-from-columns.ts +88 -0
- package/src/sources/supabase.test.ts +110 -0
- package/src/sources/supabase.ts +99 -0
- package/src/sources/with-entity-rules.test.ts +104 -0
- package/src/sources/with-entity-rules.ts +78 -0
- package/src/sources/with-relation-labels.test.ts +75 -0
- package/src/sources/with-relation-labels.ts +73 -0
- package/src/studio/bug-report.test.ts +101 -0
- package/src/studio/bug-report.ts +165 -0
- package/src/studio/cli.test.ts +187 -0
- package/src/studio/cli.ts +112 -0
- package/src/studio/csv.test.ts +90 -0
- package/src/studio/csv.ts +165 -0
- package/src/studio/db-connect-string.test.ts +94 -0
- package/src/studio/db-connect-string.ts +128 -0
- package/src/studio/emit-project.test.ts +923 -0
- package/src/studio/emit-project.ts +1273 -0
- package/src/studio/emit-schema.test.ts +94 -0
- package/src/studio/emit-schema.ts +920 -0
- package/src/studio/index.ts +195 -0
- package/src/studio/introspect-db.test.ts +186 -0
- package/src/studio/introspect-db.ts +312 -0
- package/src/studio/introspect-prisma.test.ts +99 -0
- package/src/studio/introspect-prisma.ts +175 -0
- package/src/studio/introspect.test.ts +172 -0
- package/src/studio/introspect.ts +310 -0
- package/src/studio/pipeline.test.ts +42 -0
- package/src/studio/project-robust.test.ts +157 -0
- package/src/studio/project.test.ts +473 -0
- package/src/studio/project.ts +916 -0
- package/src/studio/sample-data.test.ts +58 -0
- package/src/studio/sample-data.ts +200 -0
- package/src/studio/samples/ats.ts +202 -0
- package/src/studio/samples/clinic.ts +177 -0
- package/src/studio/samples/crm.ts +250 -0
- package/src/studio/samples/ecommerce.ts +187 -0
- package/src/studio/samples/events.ts +199 -0
- package/src/studio/samples/fleet.ts +184 -0
- package/src/studio/samples/gym.ts +213 -0
- package/src/studio/samples/hr.ts +193 -0
- package/src/studio/samples/index.ts +55 -0
- package/src/studio/samples/insurance.ts +195 -0
- package/src/studio/samples/inventory.ts +182 -0
- package/src/studio/samples/invoicing.ts +162 -0
- package/src/studio/samples/library.ts +180 -0
- package/src/studio/samples/live-data.test.ts +98 -0
- package/src/studio/samples/live-data.ts +308 -0
- package/src/studio/samples/projects.ts +190 -0
- package/src/studio/samples/realestate.ts +196 -0
- package/src/studio/samples/restaurant.ts +187 -0
- package/src/studio/samples/samples.test.ts +208 -0
- package/src/studio/samples/school.ts +197 -0
- package/src/studio/samples/seed-floor.test.ts +25 -0
- package/src/studio/samples/shared.ts +305 -0
- package/src/studio/samples/subscriptions.ts +183 -0
- package/src/studio/samples/support.ts +182 -0
- package/src/studio/scaffold-app.test.ts +91 -0
- package/src/studio/scaffold-app.ts +161 -0
- package/src/studio/scaffold.test.ts +178 -0
- package/src/studio/scaffold.ts +374 -0
- package/src/studio/themes.ts +172 -0
- package/src/studio/verify.test.ts +47 -0
- package/src/studio/verify.ts +79 -0
- package/src/sveltekit/in-memory.test.ts +104 -0
- package/src/sveltekit/in-memory.ts +129 -0
- package/src/sveltekit/index.ts +23 -0
- package/src/sveltekit/query-plan.test.ts +109 -0
- package/src/sveltekit/query-plan.ts +125 -0
- package/src/sveltekit/sql-source.test.ts +185 -0
- package/src/sveltekit/sql-source.ts +166 -0
- package/src/sveltekit/sql.test.ts +80 -0
- package/src/sveltekit/sql.ts +131 -0
- package/src/sveltekit/transport.test.ts +175 -0
- package/src/sveltekit/transport.ts +254 -0
- package/src/sveltekit/types.ts +11 -0
- package/src/upgrade-prompt.ts +149 -148
package/src/upgrade-prompt.ts
CHANGED
|
@@ -1,148 +1,149 @@
|
|
|
1
|
-
// Product-led-growth (PLG) upgrade nudge, shown at the *moment of intent*: the
|
|
2
|
-
// instant a developer actually calls a Pro feature (export / import / print /
|
|
3
|
-
// AI) without a license key set. Unlike the passive corner watermark
|
|
4
|
-
// (watermark.ts), this is a one-click contextual card that names the feature
|
|
5
|
-
// they just used and links straight to a free trial.
|
|
6
|
-
//
|
|
7
|
-
// Rules of the road:
|
|
8
|
-
// - Soft, never blocking. The feature already ran; this only nudges.
|
|
9
|
-
// - Shows once per session (SPA lifetime). Once shown - whether the user
|
|
10
|
-
// acts on it or closes it - it stays quiet for the rest of the session.
|
|
11
|
-
// Calling setLicenseKey() silences it before it ever appears.
|
|
12
|
-
// - Storage-free: no cookies, no localStorage, no sessionStorage. State is
|
|
13
|
-
// a single in-memory flag, so the library keeps its "zero web storage"
|
|
14
|
-
// promise (see docs/help/security.md). A hard reload may show it once
|
|
15
|
-
// more - by design; that's still a moment-of-intent nudge.
|
|
16
|
-
// - SSR-safe: every DOM access is guarded. On the server it's a no-op.
|
|
17
|
-
// - Zero dependencies, inline styles - no CSS file to import, nothing to
|
|
18
|
-
// bundle, works in any host app regardless of its styling.
|
|
19
|
-
|
|
20
|
-
const CARD_ATTR = 'data-svgrid-enterprise-upgrade'
|
|
21
|
-
const PRICING_URL = 'https://www.svgrid.com/pricing'
|
|
22
|
-
// ?ref=in-app lets us measure how many trials start from this exact prompt
|
|
23
|
-
// vs. the pricing page itself - the whole point of a moment-of-intent CTA.
|
|
24
|
-
const TRIAL_URL = 'https://www.svgrid.com/pricing?ref=in-app&utm_source=svgrid-enterprise&utm_medium=upgrade-prompt'
|
|
25
|
-
|
|
26
|
-
let shownThisSession = false
|
|
27
|
-
|
|
28
|
-
/** Human-readable labels for the Pro surfaces that gate behind a license. */
|
|
29
|
-
export type EnterpriseFeatureLabel =
|
|
30
|
-
| 'Export'
|
|
31
|
-
| 'Import'
|
|
32
|
-
| 'Print'
|
|
33
|
-
| 'AI assistant'
|
|
34
|
-
| 'Pivot'
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
if (document
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
card.style.
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
card.style.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
card.
|
|
78
|
-
card.setAttribute(
|
|
79
|
-
card.setAttribute('
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
text-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
card
|
|
137
|
-
card.querySelector('[data-act="
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
.replace(
|
|
146
|
-
.replace(
|
|
147
|
-
.replace(
|
|
148
|
-
|
|
1
|
+
// Product-led-growth (PLG) upgrade nudge, shown at the *moment of intent*: the
|
|
2
|
+
// instant a developer actually calls a Pro feature (export / import / print /
|
|
3
|
+
// AI) without a license key set. Unlike the passive corner watermark
|
|
4
|
+
// (watermark.ts), this is a one-click contextual card that names the feature
|
|
5
|
+
// they just used and links straight to a free trial.
|
|
6
|
+
//
|
|
7
|
+
// Rules of the road:
|
|
8
|
+
// - Soft, never blocking. The feature already ran; this only nudges.
|
|
9
|
+
// - Shows once per session (SPA lifetime). Once shown - whether the user
|
|
10
|
+
// acts on it or closes it - it stays quiet for the rest of the session.
|
|
11
|
+
// Calling setLicenseKey() silences it before it ever appears.
|
|
12
|
+
// - Storage-free: no cookies, no localStorage, no sessionStorage. State is
|
|
13
|
+
// a single in-memory flag, so the library keeps its "zero web storage"
|
|
14
|
+
// promise (see docs/help/security.md). A hard reload may show it once
|
|
15
|
+
// more - by design; that's still a moment-of-intent nudge.
|
|
16
|
+
// - SSR-safe: every DOM access is guarded. On the server it's a no-op.
|
|
17
|
+
// - Zero dependencies, inline styles - no CSS file to import, nothing to
|
|
18
|
+
// bundle, works in any host app regardless of its styling.
|
|
19
|
+
|
|
20
|
+
const CARD_ATTR = 'data-svgrid-enterprise-upgrade'
|
|
21
|
+
const PRICING_URL = 'https://www.svgrid.com/pricing'
|
|
22
|
+
// ?ref=in-app lets us measure how many trials start from this exact prompt
|
|
23
|
+
// vs. the pricing page itself - the whole point of a moment-of-intent CTA.
|
|
24
|
+
const TRIAL_URL = 'https://www.svgrid.com/pricing?ref=in-app&utm_source=svgrid-enterprise&utm_medium=upgrade-prompt'
|
|
25
|
+
|
|
26
|
+
let shownThisSession = false
|
|
27
|
+
|
|
28
|
+
/** Human-readable labels for the Pro surfaces that gate behind a license. */
|
|
29
|
+
export type EnterpriseFeatureLabel =
|
|
30
|
+
| 'Export'
|
|
31
|
+
| 'Import'
|
|
32
|
+
| 'Print'
|
|
33
|
+
| 'AI assistant'
|
|
34
|
+
| 'Pivot'
|
|
35
|
+
| 'Studio'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Show the contextual upgrade prompt for `feature`. No-ops if one has already
|
|
39
|
+
* been shown this session, a card is already up, or we're on the server. Safe
|
|
40
|
+
* to call on every Pro feature invocation - it self-throttles.
|
|
41
|
+
*/
|
|
42
|
+
export function showUpgradePrompt(feature?: EnterpriseFeatureLabel | string): void {
|
|
43
|
+
if (shownThisSession) return
|
|
44
|
+
if (typeof document === 'undefined' || typeof window === 'undefined') return
|
|
45
|
+
if (document.querySelector(`[${CARD_ATTR}]`)) return
|
|
46
|
+
shownThisSession = true
|
|
47
|
+
|
|
48
|
+
const card = buildCard(feature)
|
|
49
|
+
document.body.appendChild(card)
|
|
50
|
+
// Animate in on the next frame so the transition actually runs.
|
|
51
|
+
requestAnimationFrame(() => {
|
|
52
|
+
card.style.opacity = '1'
|
|
53
|
+
card.style.transform = 'translateY(0)'
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Remove the card if present and re-arm the once-per-session flag so a later
|
|
59
|
+
* `showUpgradePrompt()` can show again. Mainly for hosts that want to control
|
|
60
|
+
* the nudge themselves (and for tests).
|
|
61
|
+
*/
|
|
62
|
+
export function dismissUpgradePrompt(): void {
|
|
63
|
+
shownThisSession = false
|
|
64
|
+
if (typeof document === 'undefined') return
|
|
65
|
+
document.querySelectorAll(`[${CARD_ATTR}]`).forEach((el) => el.remove())
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// User closed or clicked through the card. Remove it, but leave
|
|
69
|
+
// `shownThisSession` set so it does not reappear for the rest of the session.
|
|
70
|
+
function close(card: HTMLElement): void {
|
|
71
|
+
card.style.opacity = '0'
|
|
72
|
+
card.style.transform = 'translateY(8px)'
|
|
73
|
+
window.setTimeout(() => card.remove(), 220)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildCard(feature?: EnterpriseFeatureLabel | string): HTMLElement {
|
|
77
|
+
const card = document.createElement('div')
|
|
78
|
+
card.setAttribute(CARD_ATTR, '1')
|
|
79
|
+
card.setAttribute('role', 'dialog')
|
|
80
|
+
card.setAttribute('aria-label', 'Unlock SvGrid Pro')
|
|
81
|
+
Object.assign(card.style, {
|
|
82
|
+
position: 'fixed',
|
|
83
|
+
bottom: '16px',
|
|
84
|
+
right: '16px',
|
|
85
|
+
zIndex: '2147483646', // one below the watermark so they never collide
|
|
86
|
+
width: '320px',
|
|
87
|
+
maxWidth: 'calc(100vw - 32px)',
|
|
88
|
+
boxSizing: 'border-box',
|
|
89
|
+
padding: '16px 16px 14px',
|
|
90
|
+
background: '#0f172a',
|
|
91
|
+
color: '#e2e8f0',
|
|
92
|
+
borderRadius: '12px',
|
|
93
|
+
border: '1px solid rgba(99,102,241,0.4)',
|
|
94
|
+
boxShadow: '0 12px 40px rgba(0,0,0,0.45)',
|
|
95
|
+
fontFamily: '-apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
96
|
+
fontSize: '13px',
|
|
97
|
+
lineHeight: '1.45',
|
|
98
|
+
opacity: '0',
|
|
99
|
+
transform: 'translateY(8px)',
|
|
100
|
+
transition: 'opacity 220ms ease, transform 220ms ease',
|
|
101
|
+
} as Partial<CSSStyleDeclaration> as CSSStyleDeclaration)
|
|
102
|
+
|
|
103
|
+
const featureName = feature ? String(feature) : 'This'
|
|
104
|
+
const featurePhrase = feature
|
|
105
|
+
? `<strong style="color:#fff">${escapeHtml(featureName)}</strong> is a Pro feature.`
|
|
106
|
+
: `You just used a <strong style="color:#fff">Pro</strong> feature.`
|
|
107
|
+
|
|
108
|
+
card.innerHTML = `
|
|
109
|
+
<button type="button" data-act="x" aria-label="Dismiss"
|
|
110
|
+
style="position:absolute;top:8px;right:8px;width:24px;height:24px;display:flex;
|
|
111
|
+
align-items:center;justify-content:center;background:transparent;border:0;
|
|
112
|
+
color:#94a3b8;font-size:18px;line-height:1;cursor:pointer;border-radius:6px;">×</button>
|
|
113
|
+
<div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;">
|
|
114
|
+
<span style="display:inline-block;background:#4f46e5;color:#fff;font-size:10px;
|
|
115
|
+
font-weight:700;letter-spacing:0.06em;padding:2px 7px;border-radius:999px;">PRO</span>
|
|
116
|
+
<span style="font-weight:700;color:#fff;">Unlock SvGrid Pro</span>
|
|
117
|
+
</div>
|
|
118
|
+
<p style="margin:0 0 12px;color:#cbd5e1;">
|
|
119
|
+
${featurePhrase} It runs in evaluation with a watermark - start a free trial
|
|
120
|
+
to remove it and ship to production.
|
|
121
|
+
</p>
|
|
122
|
+
<div style="display:flex;gap:8px;align-items:center;">
|
|
123
|
+
<a data-act="trial" href="${TRIAL_URL}" target="_blank" rel="noopener noreferrer"
|
|
124
|
+
style="flex:1;text-align:center;background:#6366f1;color:#fff;font-weight:600;
|
|
125
|
+
text-decoration:none;padding:8px 12px;border-radius:8px;">Start free trial</a>
|
|
126
|
+
<a data-act="pricing" href="${PRICING_URL}" target="_blank" rel="noopener noreferrer"
|
|
127
|
+
style="color:#a5b4fc;text-decoration:none;padding:8px 6px;font-weight:600;">Pricing</a>
|
|
128
|
+
</div>
|
|
129
|
+
<p style="margin:10px 0 0;font-size:11px;color:#64748b;">
|
|
130
|
+
Already licensed? Call <code style="color:#94a3b8;">setLicenseKey()</code> at startup to hide this.
|
|
131
|
+
</p>
|
|
132
|
+
`
|
|
133
|
+
|
|
134
|
+
card.querySelector('[data-act="x"]')?.addEventListener('click', () => close(card))
|
|
135
|
+
// Clicking through to a trial / pricing also counts as "handled" - close the
|
|
136
|
+
// card, but let the link open in its new tab first.
|
|
137
|
+
card.querySelector('[data-act="trial"]')?.addEventListener('click', () => close(card))
|
|
138
|
+
card.querySelector('[data-act="pricing"]')?.addEventListener('click', () => close(card))
|
|
139
|
+
|
|
140
|
+
return card
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function escapeHtml(s: string): string {
|
|
144
|
+
return s
|
|
145
|
+
.replace(/&/g, '&')
|
|
146
|
+
.replace(/</g, '<')
|
|
147
|
+
.replace(/>/g, '>')
|
|
148
|
+
.replace(/"/g, '"')
|
|
149
|
+
}
|