@svgrid/enterprise 3.1.7 → 3.1.8

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>SvGrid Studio - Designer</title>
7
- <script type="module" crossorigin src="./assets/index-DtBIaQno.js"></script>
7
+ <script type="module" crossorigin src="./assets/index-Obk8sI77.js"></script>
8
8
  <link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-Dd_uD5pT.js">
9
9
  <link rel="modulepreload" crossorigin href="./assets/disclose-version-CIm4S9xS.js">
10
10
  <link rel="modulepreload" crossorigin href="./assets/cell-formatting-BWrW_O0n.js">
@@ -2054,7 +2054,7 @@ var SOURCE = /\.(ts|js|svelte)$/;
2054
2054
  function toSvelteKit3(files) {
2055
2055
  const paths = new Set(files.map((f) => f.path));
2056
2056
  const adapter = adapterOf(files);
2057
- const envNames = /* @__PURE__ */ new Set();
2057
+ const envNames = /* @__PURE__ */ new Map();
2058
2058
  const out = [];
2059
2059
  for (const file of files) {
2060
2060
  if (file.path === "svelte.config.js") continue;
@@ -2090,7 +2090,7 @@ function toSvelteKit3(files) {
2090
2090
  }
2091
2091
  out.push(file);
2092
2092
  }
2093
- if (envNames.size) out.push(envModule([...envNames].sort()));
2093
+ if (envNames.size) out.push(envModule([...envNames].sort(([a], [b]) => a.localeCompare(b))));
2094
2094
  return out;
2095
2095
  }
2096
2096
  function adapterOf(files) {
@@ -2159,18 +2159,22 @@ function rewriteLibImports(src, paths) {
2159
2159
  /**
2160
2160
  * `import { env } from '$env/dynamic/private'` + `env.X`
2161
2161
  * -> `import { X } from '$app/env/private'` + `X`
2162
- * Every name read is collected so src/env.ts can declare it, which v3 requires.
2162
+ * and the same for `$env/dynamic/public` -> `$app/env/public` (the Supabase
2163
+ * client reads PUBLIC_SUPABASE_* this way). Every name read is collected so
2164
+ * src/env.ts can declare it, which v3 requires; public ones are declared
2165
+ * `public: true`, or `$app/env/public` would not export them.
2163
2166
  */
2164
2167
  function rewriteEnv(src, envNames) {
2165
- if (!/from\s+['"]\$env\/dynamic\/private['"]/.test(src)) return src;
2168
+ const kind = /from\s+['"]\$env\/dynamic\/private['"]/.test(src) ? "private" : /from\s+['"]\$env\/dynamic\/public['"]/.test(src) ? "public" : null;
2169
+ if (!kind) return src;
2166
2170
  const used = /* @__PURE__ */ new Set();
2167
2171
  const body = src.replace(/(?<![.\w])env\.([A-Z_][A-Z0-9_]*)/g, (_m, name) => {
2168
2172
  used.add(name);
2169
2173
  return name;
2170
2174
  });
2171
- for (const n of used) envNames.add(n);
2175
+ for (const n of used) envNames.set(n, kind === "public" || envNames.get(n) === true);
2172
2176
  const names = [...used].sort();
2173
- return body.replace(/import\s*\{\s*env\s*\}\s*from\s*(['"])\$env\/dynamic\/private\1/, names.length ? `import { ${names.join(", ")} } from '$app/env/private'` : "");
2177
+ return body.replace(new RegExp(`import\\s*\\{\\s*env\\s*\\}\\s*from\\s*(['"])\\$env\\/dynamic\\/${kind}\\1`), names.length ? `import { ${names.join(", ")} } from '$app/env/${kind}'` : "");
2174
2178
  }
2175
2179
  /**
2176
2180
  * Types that moved out of `@sveltejs/kit`, and the deprecated `json` helper.
@@ -2198,7 +2202,7 @@ function envModule(names) {
2198
2202
  // SvelteKit 3 reads only the variables declared here. A missing one comes
2199
2203
  // through as '' - every read in this app already falls back on that
2200
2204
  // (a dev default, '?? ""', or an if), so that is the intended behaviour.
2201
- export const variables = defineEnvVars({\n${names.map((n) => ` ${n}: { schema: (input) => input ?? '' },`).join("\n")}\n})\n`
2205
+ export const variables = defineEnvVars({\n${names.map(([n, pub]) => ` ${n}: { ${pub ? "public: true, " : ""}schema: (input) => input ?? '' },`).join("\n")}\n})\n`
2202
2206
  };
2203
2207
  }
2204
2208
  //#endregion
@@ -9297,7 +9301,7 @@ var GENERATED_UI_SURFACE = {
9297
9301
  "key": "rowNumberWidth",
9298
9302
  "label": "Row Number Width",
9299
9303
  "type": "number",
9300
- "description": "Width (px) of the row-number column. Defaults to 56, which fits up to \"99,999\"; bump this when the dataset crosses six digits so the largest row number stays fully visible at the bottom of a scroll.",
9304
+ "description": "Width (px) of the row-number column. By default it fits the largest row number: 56px up to four digits, then 9px wider per digit (from `data.length`, or `rowCount` on a server-paged grid). Set it to pin a width, for example when a theme uses a much larger font.",
9301
9305
  "group": "common"
9302
9306
  },
9303
9307
  {
@@ -16341,7 +16345,7 @@ function hasFieldConditions(schema) {
16341
16345
  *
16342
16346
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
16343
16347
  */
16344
- var SVGRID_VERSION = "3.1.7";
16348
+ var SVGRID_VERSION = "3.1.8";
16345
16349
  /**
16346
16350
  * The version of `@svgrid/grid`, which releases on its own line: enterprise is
16347
16351
  * on 3.1.x while the grid is on 3.0.x.
@@ -16354,7 +16358,7 @@ var SVGRID_VERSION = "3.1.7";
16354
16358
  *
16355
16359
  * `version.test.ts` asserts this matches packages/grid/package.json.
16356
16360
  */
16357
- var GRID_VERSION = "3.0.10";
16361
+ var GRID_VERSION = "3.0.11";
16358
16362
  //#endregion
16359
16363
  //#region src/studio/emit-project.ts
16360
16364
  var has = (blocks, kind) => blocks.some((b) => b.config.kind === kind);
@@ -18441,6 +18445,7 @@ function emitSsrGridScreen(schema, screen, routed, accessEnabled, screenIds, byN
18441
18445
  const facetPanel = screen.blocks.find((b) => b.config.kind === "filter")?.config;
18442
18446
  const pageSize = grid.pageSize && grid.pageSize > 0 ? grid.pageSize : 25;
18443
18447
  const wantsFilter = grid.filterable !== false;
18448
+ const wantsSort = grid.sortable !== false;
18444
18449
  const idField = schema.idField ?? schema.fields.find((f) => f.primaryKey)?.field ?? "id";
18445
18450
  const isFormHidden = (f) => f.hidden === true || typeof f.hidden === "object" && !!f.hidden.form;
18446
18451
  const editable = schema.fields.filter((f) => f.field !== idField && !f.primaryKey && !f.readonly && !f.computed && !f.formula && !isFormHidden(f));
@@ -18738,7 +18743,7 @@ ${wantsFilter ? `
18738
18743
  ${facetForm}
18739
18744
  <SvGrid
18740
18745
  data={data.rows}
18741
- {columns}
18746
+ {columns}${wantsSort ? "\n sortable" : ""}
18742
18747
  externalSort
18743
18748
  initialSorting={data.sort}
18744
18749
  showPagination
@@ -21156,13 +21161,28 @@ function randomSecret(bytes = 32) {
21156
21161
  globalThis.crypto.getRandomValues(buf);
21157
21162
  return Array.from(buf, (b) => b.toString(16).padStart(2, "0")).join("");
21158
21163
  }
21164
+ /** The Supabase project the app connects to, when the model holds one: the
21165
+ * project-wide connection, else the first Supabase-bound entity's. */
21166
+ function supabaseConnOf(project) {
21167
+ const hit = [project.supabase, ...Object.values(project.dataSources ?? {}).filter((s) => s.kind === "supabase")].find((c) => c?.url && c?.key);
21168
+ return hit ? {
21169
+ url: hit.url,
21170
+ key: hit.key
21171
+ } : null;
21172
+ }
21159
21173
  /** A ready-to-run, git-ignored `.env`: the `.env.example` template with a real
21160
21174
  * random `SESSION_SECRET` filled in, so the app is secure out of the box (no
21161
- * hardcoded dev secret). Only emitted when the app actually signs sessions. */
21162
- function envDotFile(allSource) {
21175
+ * hardcoded dev secret), and the Supabase URL + anon key the model already
21176
+ * holds, so a Supabase app runs as generated instead of failing on an empty
21177
+ * URL. Only emitted when there is something to fill in. */
21178
+ function envDotFile(allSource, project) {
21163
21179
  const example = envExample(allSource);
21164
- if (!example || !allSource.includes("SESSION_SECRET")) return null;
21165
- return example.replace("SESSION_SECRET=change-me-to-a-long-random-string", `SESSION_SECRET=${randomSecret()}`);
21180
+ if (!example) return null;
21181
+ const supa = allSource.includes("PUBLIC_SUPABASE_URL") ? supabaseConnOf(project) : null;
21182
+ if (!allSource.includes("SESSION_SECRET") && !supa) return null;
21183
+ let env = example.replace("SESSION_SECRET=change-me-to-a-long-random-string", `SESSION_SECRET=${randomSecret()}`);
21184
+ if (supa) env = env.replace(/^PUBLIC_SUPABASE_URL=$/m, `PUBLIC_SUPABASE_URL=${supa.url}`).replace(/^PUBLIC_SUPABASE_ANON_KEY=$/m, `PUBLIC_SUPABASE_ANON_KEY=${supa.key}`);
21185
+ return env;
21166
21186
  }
21167
21187
  /** A `.env.example` listing the env vars the generated code reads, when any. */
21168
21188
  function envExample(allSource) {
@@ -21448,10 +21468,10 @@ function emitStudioAppBundle(project) {
21448
21468
  description: "Environment variables the app reads (copy to .env and fill in).",
21449
21469
  contents: envExample(allSource)
21450
21470
  }] : [],
21451
- ...envDotFile(allSource) ? [{
21471
+ ...envDotFile(allSource, project) ? [{
21452
21472
  path: ".env",
21453
- description: "Local env (git-ignored): a real random SESSION_SECRET is pre-filled so sessions are secure out of the box; fill in the rest.",
21454
- contents: envDotFile(allSource)
21473
+ description: "Local env (git-ignored): a real random SESSION_SECRET and the Supabase connection the design holds are pre-filled, so the app runs as generated; fill in the rest.",
21474
+ contents: envDotFile(allSource, project)
21455
21475
  }] : [],
21456
21476
  {
21457
21477
  path: "src/app.css",
@@ -2540,6 +2540,9 @@ function emitSsrGridScreen(schema, screen, routed, accessEnabled, screenIds, byN
2540
2540
  const facetPanel = screen.blocks.find((b) => b.config.kind === 'filter')?.config;
2541
2541
  const pageSize = grid.pageSize && grid.pageSize > 0 ? grid.pageSize : 25;
2542
2542
  const wantsFilter = grid.filterable !== false;
2543
+ // externalSort alone only renders the indicator; without `sortable` a header
2544
+ // click never reaches onSortingChange, so the URL (and the load) never sorts.
2545
+ const wantsSort = grid.sortable !== false;
2543
2546
  const idField = schema.idField ?? schema.fields.find((f) => f.primaryKey)?.field ?? 'id';
2544
2547
  const isFormHidden = (f) => f.hidden === true || (typeof f.hidden === 'object' && !!f.hidden.form);
2545
2548
  const editable = schema.fields.filter((f) => f.field !== idField && !f.primaryKey && !f.readonly && !f.computed && !f.formula && !isFormHidden(f));
@@ -2901,7 +2904,7 @@ ${wantsFilter ? `
2901
2904
  ${facetForm}
2902
2905
  <SvGrid
2903
2906
  data={data.rows}
2904
- {columns}
2907
+ {columns}${wantsSort ? '\n sortable' : ''}
2905
2908
  externalSort
2906
2909
  initialSorting={data.sort}
2907
2910
  showPagination
@@ -5171,14 +5174,30 @@ function randomSecret(bytes = 32) {
5171
5174
  globalThis.crypto.getRandomValues(buf);
5172
5175
  return Array.from(buf, (b) => b.toString(16).padStart(2, '0')).join('');
5173
5176
  }
5177
+ /** The Supabase project the app connects to, when the model holds one: the
5178
+ * project-wide connection, else the first Supabase-bound entity's. */
5179
+ function supabaseConnOf(project) {
5180
+ const candidates = [project.supabase, ...Object.values(project.dataSources ?? {}).filter((s) => s.kind === 'supabase')];
5181
+ const hit = candidates.find((c) => c?.url && c?.key);
5182
+ return hit ? { url: hit.url, key: hit.key } : null;
5183
+ }
5174
5184
  /** A ready-to-run, git-ignored `.env`: the `.env.example` template with a real
5175
5185
  * random `SESSION_SECRET` filled in, so the app is secure out of the box (no
5176
- * hardcoded dev secret). Only emitted when the app actually signs sessions. */
5177
- function envDotFile(allSource) {
5186
+ * hardcoded dev secret), and the Supabase URL + anon key the model already
5187
+ * holds, so a Supabase app runs as generated instead of failing on an empty
5188
+ * URL. Only emitted when there is something to fill in. */
5189
+ function envDotFile(allSource, project) {
5178
5190
  const example = envExample(allSource);
5179
- if (!example || !allSource.includes('SESSION_SECRET'))
5191
+ if (!example)
5192
+ return null;
5193
+ const supa = allSource.includes('PUBLIC_SUPABASE_URL') ? supabaseConnOf(project) : null;
5194
+ if (!allSource.includes('SESSION_SECRET') && !supa)
5180
5195
  return null;
5181
- return example.replace('SESSION_SECRET=change-me-to-a-long-random-string', `SESSION_SECRET=${randomSecret()}`);
5196
+ let env = example.replace('SESSION_SECRET=change-me-to-a-long-random-string', `SESSION_SECRET=${randomSecret()}`);
5197
+ // The anon key is public / browser-safe; access is governed by RLS.
5198
+ if (supa)
5199
+ env = env.replace(/^PUBLIC_SUPABASE_URL=$/m, `PUBLIC_SUPABASE_URL=${supa.url}`).replace(/^PUBLIC_SUPABASE_ANON_KEY=$/m, `PUBLIC_SUPABASE_ANON_KEY=${supa.key}`);
5200
+ return env;
5182
5201
  }
5183
5202
  /** A `.env.example` listing the env vars the generated code reads, when any. */
5184
5203
  function envExample(allSource) {
@@ -5480,7 +5499,7 @@ export function emitStudioAppBundle(project) {
5480
5499
  rootLayoutModule(project),
5481
5500
  ...SCAFFOLD_STATIC,
5482
5501
  ...(envExample(allSource) ? [{ path: '.env.example', description: 'Environment variables the app reads (copy to .env and fill in).', contents: envExample(allSource) }] : []),
5483
- ...(envDotFile(allSource) ? [{ path: '.env', description: 'Local env (git-ignored): a real random SESSION_SECRET is pre-filled so sessions are secure out of the box; fill in the rest.', contents: envDotFile(allSource) }] : []),
5502
+ ...(envDotFile(allSource, project) ? [{ path: '.env', description: 'Local env (git-ignored): a real random SESSION_SECRET and the Supabase connection the design holds are pre-filled, so the app runs as generated; fill in the rest.', contents: envDotFile(allSource, project) }] : []),
5484
5503
  { path: 'src/app.css', description: 'App theme tokens + page styles.', contents: appCss(project) },
5485
5504
  // Your styles: a dedicated CSS file the layout imports AFTER app.css, so its rules
5486
5505
  // win. Edited in the designer's Styles panel; regenerated from the model.
@@ -24,7 +24,8 @@ const SOURCE = /\.(ts|js|svelte)$/;
24
24
  export function toSvelteKit3(files) {
25
25
  const paths = new Set(files.map((f) => f.path));
26
26
  const adapter = adapterOf(files);
27
- const envNames = new Set();
27
+ // Every env var a source reads, and whether it is public (client-side).
28
+ const envNames = new Map();
28
29
  const out = [];
29
30
  for (const file of files) {
30
31
  // svelte.config.js is gone: its adapter and preprocess move into vite.config.ts.
@@ -50,7 +51,7 @@ export function toSvelteKit3(files) {
50
51
  out.push(file);
51
52
  }
52
53
  if (envNames.size)
53
- out.push(envModule([...envNames].sort()));
54
+ out.push(envModule([...envNames].sort(([a], [b]) => a.localeCompare(b))));
54
55
  return out;
55
56
  }
56
57
  /* ---------------------------------------------------------------- config */
@@ -143,10 +144,15 @@ function rewriteLibImports(src, paths) {
143
144
  /**
144
145
  * `import { env } from '$env/dynamic/private'` + `env.X`
145
146
  * -> `import { X } from '$app/env/private'` + `X`
146
- * Every name read is collected so src/env.ts can declare it, which v3 requires.
147
+ * and the same for `$env/dynamic/public` -> `$app/env/public` (the Supabase
148
+ * client reads PUBLIC_SUPABASE_* this way). Every name read is collected so
149
+ * src/env.ts can declare it, which v3 requires; public ones are declared
150
+ * `public: true`, or `$app/env/public` would not export them.
147
151
  */
148
152
  function rewriteEnv(src, envNames) {
149
- if (!/from\s+['"]\$env\/dynamic\/private['"]/.test(src))
153
+ const kind = /from\s+['"]\$env\/dynamic\/private['"]/.test(src) ? 'private'
154
+ : /from\s+['"]\$env\/dynamic\/public['"]/.test(src) ? 'public' : null;
155
+ if (!kind)
150
156
  return src;
151
157
  const used = new Set();
152
158
  // `(?<![.\w])` keeps `process.env.X` untouched; only the imported `env` changes.
@@ -155,9 +161,9 @@ function rewriteEnv(src, envNames) {
155
161
  return name;
156
162
  });
157
163
  for (const n of used)
158
- envNames.add(n);
164
+ envNames.set(n, kind === 'public' || envNames.get(n) === true);
159
165
  const names = [...used].sort();
160
- return body.replace(/import\s*\{\s*env\s*\}\s*from\s*(['"])\$env\/dynamic\/private\1/, names.length ? `import { ${names.join(', ')} } from '$app/env/private'` : '');
166
+ return body.replace(new RegExp(`import\\s*\\{\\s*env\\s*\\}\\s*from\\s*(['"])\\$env\\/dynamic\\/${kind}\\1`), names.length ? `import { ${names.join(', ')} } from '$app/env/${kind}'` : '');
161
167
  }
162
168
  /**
163
169
  * Types that moved out of `@sveltejs/kit`, and the deprecated `json` helper.
@@ -181,7 +187,7 @@ function rewriteKitImports(src) {
181
187
  }
182
188
  /* ------------------------------------------------------------------- env */
183
189
  function envModule(names) {
184
- const decls = names.map((n) => ` ${n}: { schema: (input) => input ?? '' },`).join('\n');
190
+ const decls = names.map(([n, pub]) => ` ${n}: { ${pub ? 'public: true, ' : ''}schema: (input) => input ?? '' },`).join('\n');
185
191
  return {
186
192
  path: 'src/env.ts',
187
193
  description: 'Environment variables the app reads (SvelteKit 3 requires declaring them).',
@@ -7180,7 +7180,7 @@ export const GENERATED_UI_SURFACE = {
7180
7180
  "key": "rowNumberWidth",
7181
7181
  "label": "Row Number Width",
7182
7182
  "type": "number",
7183
- "description": "Width (px) of the row-number column. Defaults to 56, which fits up to \"99,999\"; bump this when the dataset crosses six digits so the largest row number stays fully visible at the bottom of a scroll.",
7183
+ "description": "Width (px) of the row-number column. By default it fits the largest row number: 56px up to four digits, then 9px wider per digit (from `data.length`, or `rowCount` on a server-paged grid). Set it to pin a width, for example when a theme uses a much larger font.",
7184
7184
  "group": "common"
7185
7185
  },
7186
7186
  {
package/dist/version.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
12
12
  */
13
- export declare const SVGRID_VERSION = "3.1.7";
13
+ export declare const SVGRID_VERSION = "3.1.8";
14
14
  /**
15
15
  * The version of `@svgrid/grid`, which releases on its own line: enterprise is
16
16
  * on 3.1.x while the grid is on 3.0.x.
@@ -23,4 +23,4 @@ export declare const SVGRID_VERSION = "3.1.7";
23
23
  *
24
24
  * `version.test.ts` asserts this matches packages/grid/package.json.
25
25
  */
26
- export declare const GRID_VERSION = "3.0.10";
26
+ export declare const GRID_VERSION = "3.0.11";
package/dist/version.js CHANGED
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * `version.test.ts` asserts this matches `package.json`, so the two cannot drift.
12
12
  */
13
- export const SVGRID_VERSION = '3.1.7';
13
+ export const SVGRID_VERSION = '3.1.8';
14
14
  /**
15
15
  * The version of `@svgrid/grid`, which releases on its own line: enterprise is
16
16
  * on 3.1.x while the grid is on 3.0.x.
@@ -23,4 +23,4 @@ export const SVGRID_VERSION = '3.1.7';
23
23
  *
24
24
  * `version.test.ts` asserts this matches packages/grid/package.json.
25
25
  */
26
- export const GRID_VERSION = '3.0.10';
26
+ export const GRID_VERSION = '3.0.11';
@@ -6149,7 +6149,11 @@ function ta(e, t) {
6149
6149
  let J = D(G({
6150
6150
  left: [...s.initialColumnPinning?.left ?? []],
6151
6151
  right: [...s.initialColumnPinning?.right ?? []]
6152
- })), ue = D(0), de = D(0), fe = D(0), pe = q(() => s.rowNumberWidth ?? 56), Y = q(() => s.showDetailToggle === !0);
6152
+ })), ue = D(0), de = D(0), fe = D(0), pe = q(function() {
6153
+ if (s.rowNumberWidth != null) return s.rowNumberWidth;
6154
+ let e = Math.max(s.data?.length ?? 0, s.rowCount ?? 0);
6155
+ return Math.max(56, 18 + 9 * String(e).length);
6156
+ }), Y = q(() => s.showDetailToggle === !0);
6153
6157
  function me(e, t) {
6154
6158
  let n = e.original;
6155
6159
  if (s.isDetailRow?.(n, t)) return null;
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "commercial",
5
5
  "url": "https://svgrid.com/pricing"
6
6
  },
7
- "version": "3.1.7",
7
+ "version": "3.1.8",
8
8
  "description": "Enterprise feature pack for SvGrid: the server-side row model (lazy grouping, tree, pivot, transactions, selection across unloaded rows), Excel (xlsx) and PDF export, Excel/CSV/JSON import, pivot tables with a drag-and-drop designer, paginated print, Kanban board and scheduler renderers, no-code alerts and batch editing. CSV, TSV and JSON export are already free in @svgrid/grid. Requires a paid license key.",
9
9
  "license": "SEE LICENSE IN LICENSE",
10
10
  "author": "jQWidgets <sales@jqwidgets.com>",
@@ -105,7 +105,7 @@
105
105
  "jszip": "^3.10.0",
106
106
  "pdfmake": "^0.2.0",
107
107
  "svelte": "^5.0.0",
108
- "@svgrid/grid": "^3.0.10"
108
+ "@svgrid/grid": "^3.0.11"
109
109
  },
110
110
  "peerDependenciesMeta": {
111
111
  "jszip": {
@@ -123,7 +123,7 @@
123
123
  "svelte": "^5.55.5",
124
124
  "typescript": "6.0.3",
125
125
  "vite": "^8.2.1",
126
- "@svgrid/grid": "^3.0.10"
126
+ "@svgrid/grid": "^3.0.11"
127
127
  },
128
128
  "repository": {
129
129
  "type": "git",