@svgrid/enterprise 3.1.21 → 3.1.23

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.
Files changed (89) hide show
  1. package/dist/SvGridBoard.svelte +39 -0
  2. package/dist/SvGridGallery.svelte +23 -0
  3. package/dist/SvGridRowCount.svelte +23 -0
  4. package/dist/SvGridRowCount.svelte.d.ts +6 -0
  5. package/dist/SvGridScheduler.svelte +25 -7
  6. package/dist/cdn/svgrid-enterprise.svelte-external.js +13838 -13554
  7. package/dist/designer/assets/GridFooter-DKMfZpL4.js +2 -0
  8. package/dist/designer/assets/GridMenus-DWDghydL.js +6 -0
  9. package/dist/designer/assets/{PinSplitter-C5AwA1xV.js → PinSplitter-BfIjd7pi.js} +1 -1
  10. package/dist/designer/assets/grid-extension.svelte-G1ng0xd2.js +1 -0
  11. package/dist/designer/assets/index-CHx3F4Ij.css +1 -0
  12. package/dist/designer/assets/{index-DLJjuVA4.js → index-CIxqRzKJ.js} +324 -324
  13. package/dist/designer/assets/merges-Bg-KqPEl.js +1 -0
  14. package/dist/designer/index.html +3 -3
  15. package/dist/expressions/compile.js +11 -7
  16. package/dist/expressions/evaluate.js +4 -0
  17. package/dist/expressions/expression-columns.d.ts +4 -1
  18. package/dist/expressions/expression-columns.js +12 -3
  19. package/dist/expressions/parse.js +19 -7
  20. package/dist/fields/RecordView.svelte +5 -2
  21. package/dist/fields/activity.svelte.d.ts +5 -2
  22. package/dist/fields/activity.svelte.js +4 -3
  23. package/dist/fields/grid-access.d.ts +1 -1
  24. package/dist/fields/grid-access.js +13 -3
  25. package/dist/fields/index.d.ts +18 -0
  26. package/dist/fields/index.js +31 -0
  27. package/dist/filter-labels.d.ts +16 -0
  28. package/dist/filter-labels.js +83 -0
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +7 -0
  31. package/dist/install.js +8 -0
  32. package/dist/node/studio.js +12 -5
  33. package/dist/relative-date-core.d.ts +40 -0
  34. package/dist/relative-date-core.js +85 -0
  35. package/dist/relative-dates.d.ts +28 -0
  36. package/dist/relative-dates.js +61 -0
  37. package/dist/review/GhostCell.svelte +60 -0
  38. package/dist/review/GhostCell.svelte.d.ts +14 -0
  39. package/dist/review/RichCellMark.svelte +72 -0
  40. package/dist/review/RichCellMark.svelte.d.ts +8 -0
  41. package/dist/review/SvReviewPanel.svelte +759 -0
  42. package/dist/review/SvReviewPanel.svelte.d.ts +16 -0
  43. package/dist/review/adapters.d.ts +79 -0
  44. package/dist/review/adapters.js +119 -0
  45. package/dist/review/agent.d.ts +52 -0
  46. package/dist/review/agent.js +232 -0
  47. package/dist/review/card-marks.svelte.d.ts +42 -0
  48. package/dist/review/card-marks.svelte.js +51 -0
  49. package/dist/review/cluster.d.ts +26 -0
  50. package/dist/review/cluster.js +377 -0
  51. package/dist/review/equal.d.ts +9 -0
  52. package/dist/review/equal.js +35 -0
  53. package/dist/review/formats.d.ts +31 -0
  54. package/dist/review/formats.js +37 -0
  55. package/dist/review/ghost.d.ts +17 -0
  56. package/dist/review/ghost.js +104 -0
  57. package/dist/review/index.d.ts +42 -0
  58. package/dist/review/index.js +36 -0
  59. package/dist/review/messages.d.ts +113 -0
  60. package/dist/review/messages.js +135 -0
  61. package/dist/review/model.svelte.d.ts +262 -0
  62. package/dist/review/model.svelte.js +883 -0
  63. package/dist/review/pending-filter.d.ts +26 -0
  64. package/dist/review/pending-filter.js +71 -0
  65. package/dist/review/rich-cells.d.ts +1 -0
  66. package/dist/review/rich-cells.js +36 -0
  67. package/dist/review/types.d.ts +83 -0
  68. package/dist/review/types.js +7 -0
  69. package/dist/row-count.d.ts +28 -0
  70. package/dist/row-count.js +39 -0
  71. package/dist/sort-blanks.d.ts +8 -0
  72. package/dist/sort-blanks.js +47 -0
  73. package/dist/studio/ui-components.generated.js +1 -1
  74. package/dist/upgrade-prompt.d.ts +1 -1
  75. package/dist/version.d.ts +2 -2
  76. package/dist/version.js +2 -2
  77. package/dist/wc/GridFooter-CKC4L36O.js +162 -0
  78. package/dist/wc/{GridMenus-DVGuqp2l.js → GridMenus-h7RsvcmI.js} +320 -303
  79. package/dist/wc/{PinSplitter-Btco0txr.js → PinSplitter-BN6ybmjs.js} +1 -1
  80. package/dist/wc/grid-extension.svelte-CDf5EUyz.js +27 -0
  81. package/dist/wc/merges-DQTOlMWM.js +109 -0
  82. package/dist/wc/sv-sheet-element.js +6753 -6792
  83. package/package.json +9 -3
  84. package/dist/designer/assets/GridFooter-CKBVItAU.js +0 -2
  85. package/dist/designer/assets/GridMenus-Dzwu7M9r.js +0 -6
  86. package/dist/designer/assets/grid-extension.svelte-BZ7AqyJI.js +0 -1
  87. package/dist/designer/assets/index-WCxj6WfJ.css +0 -1
  88. package/dist/wc/GridFooter-BgoA77TJ.js +0 -145
  89. package/dist/wc/grid-extension.svelte-CucBS4FL.js +0 -20
@@ -0,0 +1,85 @@
1
+ /** The relative date operator ids, in menu order. */
2
+ export const RELATIVE_DATE_OPERATOR_IDS = ['today', 'beforeToday', 'afterToday', 'next7Days', 'last7Days'];
3
+ const DAY_MS = 86400000;
4
+ /** Whether `op` is one of the relative date operators. */
5
+ export function isRelativeDateOperator(op) {
6
+ return RELATIVE_DATE_OPERATOR_IDS.includes(op);
7
+ }
8
+ /**
9
+ * A value as a count of local calendar days, or NaN. A bare 'YYYY-MM-DD' is
10
+ * that day in local time; `new Date()` would read it as UTC midnight, the day
11
+ * before anywhere west of Greenwich.
12
+ */
13
+ function localDayNumber(value) {
14
+ let d;
15
+ if (value instanceof Date)
16
+ d = value;
17
+ else if (typeof value === 'number')
18
+ d = new Date(value);
19
+ else if (typeof value === 'string' && value.trim()) {
20
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
21
+ d = m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : new Date(value);
22
+ }
23
+ else
24
+ return NaN;
25
+ if (Number.isNaN(d.getTime()))
26
+ return NaN;
27
+ return Math.round(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / DAY_MS);
28
+ }
29
+ /** The inclusive range of local day numbers an operator keeps. */
30
+ function dayRange(op, now) {
31
+ const t = localDayNumber(now);
32
+ switch (op) {
33
+ case 'today':
34
+ return [t, t];
35
+ case 'beforeToday':
36
+ return [-Infinity, t - 1];
37
+ case 'afterToday':
38
+ return [t + 1, Infinity];
39
+ case 'next7Days':
40
+ return [t, t + 7];
41
+ case 'last7Days':
42
+ return [t - 7, t];
43
+ }
44
+ }
45
+ /** Local 'YYYY-MM-DD' for a day number from `localDayNumber`. */
46
+ function isoFromDayNumber(day) {
47
+ return new Date(day * DAY_MS).toISOString().slice(0, 10);
48
+ }
49
+ /**
50
+ * The test for one relative date operator. "Today" is read once, here, so a
51
+ * page left open past midnight keeps the old day until the filter changes.
52
+ * A blank or unparseable cell never matches.
53
+ */
54
+ export function compileRelativeDateFilter(op, now = new Date()) {
55
+ const [lo, hi] = dayRange(op, now);
56
+ return (cellValue) => {
57
+ const day = localDayNumber(cellValue);
58
+ return day >= lo && day <= hi;
59
+ };
60
+ }
61
+ /**
62
+ * A relative date filter as the absolute one it means today, for a backend
63
+ * with no "today" of its own: `beforeToday` becomes `lessThan` today's date,
64
+ * `next7Days` becomes `between` today and a week out, and so on, with dates as
65
+ * local 'YYYY-MM-DD'. Any other filter is returned as it is.
66
+ *
67
+ * A server data source gets this applied for it. Under `externalFilter` the
68
+ * `onFiltersChange` payload keeps the relative operator, so a saved view still
69
+ * means "overdue" tomorrow; call this when you build the query.
70
+ */
71
+ export function resolveRelativeDateFilter(filter, now = new Date()) {
72
+ if (!isRelativeDateOperator(filter.operator))
73
+ return filter;
74
+ const op = filter.operator;
75
+ const [lo, hi] = dayRange(op, now);
76
+ const out = { ...filter };
77
+ delete out.valueTo;
78
+ if (op === 'beforeToday')
79
+ Object.assign(out, { operator: 'lessThan', value: isoFromDayNumber(hi + 1) });
80
+ else if (op === 'afterToday')
81
+ Object.assign(out, { operator: 'greaterThan', value: isoFromDayNumber(lo - 1) });
82
+ else
83
+ Object.assign(out, { operator: 'between', value: isoFromDayNumber(lo), valueTo: isoFromDayNumber(hi) });
84
+ return out;
85
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Relative date filters - five date operators measured from today, in whole
3
+ * local days: Today, Before today (overdue), After today, Next 7 days and
4
+ * Last 7 days. They take no value, so picking one in a date column's filter
5
+ * menu filters at once. They plug into the grid's `filterOperators` seam, so a
6
+ * grid without this module carries none of the code.
7
+ *
8
+ * Like the rest of Enterprise it runs without a license key during the
9
+ * evaluation; the grid shows the watermark and a one-time console notice.
10
+ *
11
+ * ```ts
12
+ * import { enableRelativeDateFilters } from '@svgrid/enterprise'
13
+ * enableRelativeDateFilters()
14
+ * // then: a column with cellDataType 'date' or 'dateString' offers them
15
+ * api.setFilter('due', { operator: 'beforeToday' })
16
+ * ```
17
+ */
18
+ import { type GridFilterOperator } from '@svgrid/grid';
19
+ import { type RelativeDateOperator } from './relative-date-core.js';
20
+ export { RELATIVE_DATE_OPERATOR_IDS, isRelativeDateOperator, compileRelativeDateFilter, resolveRelativeDateFilter, type RelativeDateOperator, } from './relative-date-core.js';
21
+ /** The operators as the grid's `filterOperators` seam takes them. */
22
+ export declare const relativeDateOperators: Record<RelativeDateOperator, GridFilterOperator>;
23
+ /**
24
+ * Add the relative date operators to every grid's date filters. Idempotent:
25
+ * call it once at app start or from each component that uses them. Also
26
+ * invoked by {@link installEnterprise}.
27
+ */
28
+ export declare function enableRelativeDateFilters(): void;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Relative date filters - five date operators measured from today, in whole
3
+ * local days: Today, Before today (overdue), After today, Next 7 days and
4
+ * Last 7 days. They take no value, so picking one in a date column's filter
5
+ * menu filters at once. They plug into the grid's `filterOperators` seam, so a
6
+ * grid without this module carries none of the code.
7
+ *
8
+ * Like the rest of Enterprise it runs without a license key during the
9
+ * evaluation; the grid shows the watermark and a one-time console notice.
10
+ *
11
+ * ```ts
12
+ * import { enableRelativeDateFilters } from '@svgrid/enterprise'
13
+ * enableRelativeDateFilters()
14
+ * // then: a column with cellDataType 'date' or 'dateString' offers them
15
+ * api.setFilter('due', { operator: 'beforeToday' })
16
+ * ```
17
+ */
18
+ import { getGridExtension, registerGridExtension } from '@svgrid/grid';
19
+ import { hasValidLicense } from './license.js';
20
+ import { emitUnlicensedNudge } from './watermark.js';
21
+ import { compileRelativeDateFilter, resolveRelativeDateFilter, } from './relative-date-core.js';
22
+ export { RELATIVE_DATE_OPERATOR_IDS, isRelativeDateOperator, compileRelativeDateFilter, resolveRelativeDateFilter, } from './relative-date-core.js';
23
+ const LABELS = {
24
+ today: 'Today',
25
+ beforeToday: 'Before today',
26
+ afterToday: 'After today',
27
+ next7Days: 'Next 7 days',
28
+ last7Days: 'Last 7 days',
29
+ };
30
+ function operator(op) {
31
+ return {
32
+ label: LABELS[op],
33
+ types: ['date'],
34
+ valueless: true,
35
+ compile: () => compileRelativeDateFilter(op),
36
+ toServer: (filter) => resolveRelativeDateFilter(filter),
37
+ };
38
+ }
39
+ /** The operators as the grid's `filterOperators` seam takes them. */
40
+ export const relativeDateOperators = {
41
+ today: operator('today'),
42
+ beforeToday: operator('beforeToday'),
43
+ afterToday: operator('afterToday'),
44
+ next7Days: operator('next7Days'),
45
+ last7Days: operator('last7Days'),
46
+ };
47
+ let enabled = false;
48
+ /**
49
+ * Add the relative date operators to every grid's date filters. Idempotent:
50
+ * call it once at app start or from each component that uses them. Also
51
+ * invoked by {@link installEnterprise}.
52
+ */
53
+ export function enableRelativeDateFilters() {
54
+ if (enabled)
55
+ return;
56
+ enabled = true;
57
+ // Another module may have added operators of its own; keep them.
58
+ registerGridExtension({ filterOperators: { ...getGridExtension()?.filterOperators, ...relativeDateOperators } });
59
+ if (!hasValidLicense())
60
+ emitUnlicensedNudge();
61
+ }
@@ -0,0 +1,60 @@
1
+ <!--
2
+ A cell with a pending proposal: the proposed value, then what the cell
3
+ holds now, struck through. `own` is what the column's own `cell` returned (a
4
+ component, a snippet, text, or nothing for a plain column).
5
+ -->
6
+ <script lang="ts">
7
+ import type { Component, Snippet } from 'svelte'
8
+
9
+ let { own, before, beforeText, after, empty, title }: {
10
+ own: unknown
11
+ before: unknown
12
+ beforeText: string
13
+ after: string
14
+ /** The text for a blank proposed value, in the review's wording. */
15
+ empty: string
16
+ /** "{source} proposes {value} - reason", built by the wrapper. */
17
+ title: string
18
+ } = $props()
19
+
20
+ // The grid's render configs (`renderComponent` / `renderSnippet`) are read by
21
+ // shape: the classes are not part of the public surface.
22
+ type ComponentConfig = { component: Component<any>; props?: Record<string, unknown> }
23
+ type SnippetConfig = { snippet: Snippet<[unknown]>; params?: unknown }
24
+ const isObj = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === 'object'
25
+ const ownComponent = $derived(isObj(own) && typeof own.component === 'function' ? (own as ComponentConfig) : null)
26
+ const ownSnippet = $derived(isObj(own) && typeof own.snippet === 'function' ? (own as SnippetConfig) : null)
27
+ const ownText = $derived(typeof own === 'string' || typeof own === 'number' ? String(own) : beforeText)
28
+ </script>
29
+
30
+ <span class="sv-review-ghost" {title}>
31
+ <span class="sv-review-ghost-after">{after || empty}</span>
32
+ {#if before != null && before !== ''}
33
+ <s class="sv-review-ghost-before">
34
+ {#if ownComponent}<ownComponent.component {...ownComponent.props ?? {}} />{:else if ownSnippet}{@render ownSnippet.snippet(ownSnippet.params)}{:else}{ownText}{/if}
35
+ </s>
36
+ {/if}
37
+ </span>
38
+
39
+ <style>
40
+ /* Inline text beside the grid's own icon: a block or flex box here would drop
41
+ to a line of its own. The proposed value comes first and is plain text, so
42
+ the cell's ellipsis cuts its end. The struck value is one box, at most half
43
+ the cell: when it does not fit, the ellipsis takes it whole instead of
44
+ leaving a cut-off fragment, and the cell's title still names it. */
45
+ .sv-review-ghost-before {
46
+ display: inline-block;
47
+ max-width: 50%;
48
+ margin-left: 6px;
49
+ overflow: hidden;
50
+ text-overflow: ellipsis;
51
+ white-space: nowrap;
52
+ vertical-align: bottom;
53
+ color: var(--sg-muted, #6b7280);
54
+ text-decoration-thickness: 1px;
55
+ }
56
+ .sv-review-ghost-after {
57
+ color: var(--sg-fg, inherit);
58
+ font-weight: 600;
59
+ }
60
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Component } from 'svelte';
2
+ type $$ComponentProps = {
3
+ own: unknown;
4
+ before: unknown;
5
+ beforeText: string;
6
+ after: string;
7
+ /** The text for a blank proposed value, in the review's wording. */
8
+ empty: string;
9
+ /** "{source} proposes {value} - reason", built by the wrapper. */
10
+ title: string;
11
+ };
12
+ declare const GhostCell: Component<$$ComponentProps, {}, "">;
13
+ type GhostCell = ReturnType<typeof GhostCell>;
14
+ export default GhostCell;
@@ -0,0 +1,72 @@
1
+ <!--
2
+ The proposed value after a rich cell (a select, a rating, a person): the
3
+ cell draws as it always does, and "-> Closed" follows it. The text is the
4
+ column's own formatter's (a person's name, not their id), else the plain
5
+ formatted value.
6
+ -->
7
+ <script lang="ts">
8
+ import { formatValueForExport } from '@svgrid/grid'
9
+ import { cellProposalFor } from './card-marks.svelte'
10
+ import { showValue } from './cluster'
11
+ import { fill } from './messages'
12
+
13
+ let { ctrl, row, column }: { ctrl: any; row: any; column: any } = $props()
14
+
15
+ /** A value's label from a static options list ({ value, label } or plain values); null when there is none. */
16
+ function optionLabels(options: unknown): ((v: unknown) => string | null) | null {
17
+ if (!Array.isArray(options)) return null
18
+ const byValue = new Map<string, string>()
19
+ for (const o of options) {
20
+ if (o && typeof o === 'object' && 'value' in o) byValue.set(String((o as { value: unknown }).value), String((o as { label?: unknown }).label ?? (o as { value: unknown }).value))
21
+ else byValue.set(String(o), String(o))
22
+ }
23
+ return (v) => byValue.get(String(v)) ?? null
24
+ }
25
+
26
+ const proposal = $derived(cellProposalFor(ctrl?.props?.getRowId, row?.original, String(row?.id), column?.columnDef?.field))
27
+ const text = $derived.by(() => {
28
+ if (!proposal) return ''
29
+ const def = column?.columnDef ?? {}
30
+ const value = proposal.after
31
+ if (value == null || value === '') return proposal.empty
32
+ if (typeof def.formatter === 'function') {
33
+ try {
34
+ return String(def.formatter({ value, row, column, table: ctrl?.grid }) ?? '')
35
+ } catch {
36
+ // A formatter that needs more than a value: fall back to the value.
37
+ }
38
+ }
39
+ // A list or chips column shows option labels, not stored values.
40
+ const labelOf = optionLabels(def.editorOptions)
41
+ const one = (v: unknown) => labelOf?.(v) ?? (Array.isArray(value) ? showValue(v).replace(/^"|"$/g, '') : formatValueForExport(v, def.format))
42
+ return Array.isArray(value) ? value.map(one).join(', ') : one(value)
43
+ })
44
+ </script>
45
+
46
+ {#if proposal}
47
+ <span
48
+ class="sv-review-cellmark"
49
+ title="{fill(proposal.proposes, { source: proposal.source, value: text })}{proposal.reason ? ` - ${proposal.reason}` : ''}"
50
+ ><span aria-hidden="true">→</span> {text}</span>
51
+ {/if}
52
+
53
+ <style>
54
+ .sv-review-cellmark {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: 3px;
58
+ margin-left: 6px;
59
+ flex: none;
60
+ max-width: 60%;
61
+ overflow: hidden;
62
+ white-space: nowrap;
63
+ text-overflow: ellipsis;
64
+ font-size: 0.92em;
65
+ font-weight: 600;
66
+ color: var(--sg-fg, #111827);
67
+ }
68
+ .sv-review-cellmark > span {
69
+ color: var(--sg-muted, #6b7280);
70
+ font-weight: 400;
71
+ }
72
+ </style>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ ctrl: any;
3
+ row: any;
4
+ column: any;
5
+ };
6
+ declare const RichCellMark: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type RichCellMark = ReturnType<typeof RichCellMark>;
8
+ export default RichCellMark;