@r2digisolutions/components 0.1.6 → 0.1.7

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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/components/atoms/Checkbox/Checkbox.svelte +10 -3
  3. package/dist/components/atoms/Checkbox/Checkbox.svelte.d.ts +3 -0
  4. package/dist/components/atoms/Input/Input.svelte +17 -2
  5. package/dist/components/atoms/Input/Input.svelte.d.ts +6 -1
  6. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte +21 -0
  7. package/dist/components/atoms/MarqueeRect/MarqueeRect.svelte.d.ts +8 -0
  8. package/dist/components/atoms/Textarea/Textarea.svelte +4 -1
  9. package/dist/components/atoms/Textarea/Textarea.svelte.d.ts +1 -0
  10. package/dist/components/atoms/Toggle/Toggle.svelte +1 -1
  11. package/dist/components/molecules/BulkActionBar/BulkActionBar.svelte +19 -5
  12. package/dist/components/molecules/CodeEditor/CodeEditor.svelte +13 -10
  13. package/dist/components/molecules/ColorPicker/ColorPicker.svelte +166 -96
  14. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.d.ts +9 -0
  15. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.stories.js +8 -0
  16. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte +412 -0
  17. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanel.svelte.d.ts +14 -0
  18. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte +27 -0
  19. package/dist/components/molecules/ConditionalFormatPanel/ConditionalFormatPanelStory.svelte.d.ts +3 -0
  20. package/dist/components/molecules/ContextMenu/ContextMenu.svelte +73 -21
  21. package/dist/components/molecules/ContextMenu/ContextMenu.svelte.d.ts +8 -1
  22. package/dist/components/molecules/DateTimePicker/DateTimePicker.svelte.d.ts +1 -1
  23. package/dist/components/molecules/FormDateTimePicker/FormDateTimePicker.svelte.d.ts +1 -1
  24. package/dist/components/molecules/Gauge/Gauge.stories.d.ts +1 -1
  25. package/dist/components/molecules/InfiniteScroll/InfiniteScroll.stories.d.ts +1 -1
  26. package/dist/components/organisms/AssetPickerPage/AssetPickerPage.svelte.d.ts +1 -1
  27. package/dist/components/organisms/BacklogPage/BacklogPage.svelte.d.ts +1 -1
  28. package/dist/components/organisms/CalendarApp/CalendarApp.svelte.d.ts +1 -1
  29. package/dist/components/organisms/DataGrid/DataGrid.stories.d.ts +65 -0
  30. package/dist/components/organisms/DataGrid/DataGrid.stories.js +95 -0
  31. package/dist/components/organisms/DataGrid/DataGrid.svelte +2264 -0
  32. package/dist/components/organisms/DataGrid/DataGrid.svelte.d.ts +99 -0
  33. package/dist/components/organisms/DataGrid/DataGridStory.svelte +659 -0
  34. package/dist/components/organisms/DataGrid/DataGridStory.svelte.d.ts +11 -0
  35. package/dist/components/organisms/DataGrid/breakpoints.d.ts +10 -0
  36. package/dist/components/organisms/DataGrid/breakpoints.js +20 -0
  37. package/dist/components/organisms/DataGrid/cellEditors.d.ts +8 -0
  38. package/dist/components/organisms/DataGrid/cellEditors.js +59 -0
  39. package/dist/components/organisms/DataGrid/conditionalFormat.d.ts +11 -0
  40. package/dist/components/organisms/DataGrid/conditionalFormat.js +98 -0
  41. package/dist/components/organisms/DataGrid/filterRows.d.ts +5 -0
  42. package/dist/components/organisms/DataGrid/filterRows.js +60 -0
  43. package/dist/components/organisms/DataGrid/marks.d.ts +9 -0
  44. package/dist/components/organisms/DataGrid/marks.js +91 -0
  45. package/dist/components/organisms/DataGrid/types.d.ts +126 -0
  46. package/dist/components/organisms/DataGrid/types.js +21 -0
  47. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.d.ts +33 -0
  48. package/dist/components/organisms/ResourceStudio/ResourceStudio.stories.js +56 -0
  49. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte +830 -0
  50. package/dist/components/organisms/ResourceStudio/ResourceStudio.svelte.d.ts +68 -0
  51. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte +600 -0
  52. package/dist/components/organisms/ResourceStudio/ResourceStudioStory.svelte.d.ts +7 -0
  53. package/dist/components/organisms/ResourceStudio/fieldsToColumns.d.ts +4 -0
  54. package/dist/components/organisms/ResourceStudio/fieldsToColumns.js +20 -0
  55. package/dist/components/organisms/ResourceStudio/fieldsToSchema.d.ts +6 -0
  56. package/dist/components/organisms/ResourceStudio/fieldsToSchema.js +53 -0
  57. package/dist/components/organisms/ResourceStudio/types.d.ts +69 -0
  58. package/dist/components/organisms/ResourceStudio/types.js +15 -0
  59. package/dist/components/organisms/Scheduler/Scheduler.svelte.d.ts +1 -1
  60. package/dist/components/organisms/SchemaForm/SchemaForm.svelte +10 -3
  61. package/dist/components/organisms/SchemaForm/SchemaForm.svelte.d.ts +1 -0
  62. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.d.ts +25 -0
  63. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.stories.js +18 -0
  64. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte +192 -0
  65. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplate.svelte.d.ts +62 -0
  66. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte +129 -0
  67. package/dist/components/templates/ResourceStudioTemplate/ResourceStudioTemplateStory.svelte.d.ts +7 -0
  68. package/dist/index.d.ts +11 -0
  69. package/dist/index.js +8 -0
  70. package/dist/utils/marqueeSelect.d.ts +48 -0
  71. package/dist/utils/marqueeSelect.js +189 -0
  72. package/package.json +1 -1
@@ -0,0 +1,8 @@
1
+ import type { DataGridColumn, DataGridEditConfig } from './types.js';
2
+ /** Infer a compact editor from the current cell value. */
3
+ export declare function inferCellEditor(value: unknown): DataGridEditConfig;
4
+ /** Prefer explicit `column.edit`, otherwise infer from value. */
5
+ export declare function resolveCellEditor<T>(column: DataGridColumn<T>, value: unknown): DataGridEditConfig;
6
+ /** Coerce editor draft → value typed for `oncelledit`. */
7
+ export declare function coerceEditValue(editor: DataGridEditConfig, draft: string | number | boolean): string | number | boolean | null;
8
+ export declare function draftFromValue(value: unknown, editor: DataGridEditConfig): string | boolean;
@@ -0,0 +1,59 @@
1
+ const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(T|\s|$)/;
2
+ /** Infer a compact editor from the current cell value. */
3
+ export function inferCellEditor(value) {
4
+ if (typeof value === 'boolean')
5
+ return { type: 'boolean' };
6
+ if (typeof value === 'number' && !Number.isNaN(value))
7
+ return { type: 'number' };
8
+ if (value instanceof Date && !Number.isNaN(value.getTime()))
9
+ return { type: 'date' };
10
+ if (typeof value === 'string') {
11
+ if (ISO_DATE_RE.test(value))
12
+ return { type: 'date' };
13
+ if (value.length > 80 || value.includes('\n'))
14
+ return { type: 'textarea' };
15
+ }
16
+ return { type: 'text' };
17
+ }
18
+ /** Prefer explicit `column.edit`, otherwise infer from value. */
19
+ export function resolveCellEditor(column, value) {
20
+ if (column.edit?.type) {
21
+ return {
22
+ ...column.edit,
23
+ options: column.edit.options ?? []
24
+ };
25
+ }
26
+ return inferCellEditor(value);
27
+ }
28
+ /** Coerce editor draft → value typed for `oncelledit`. */
29
+ export function coerceEditValue(editor, draft) {
30
+ switch (editor.type) {
31
+ case 'boolean':
32
+ return Boolean(draft);
33
+ case 'number': {
34
+ if (draft === '' || draft == null)
35
+ return null;
36
+ const n = typeof draft === 'number' ? draft : Number(draft);
37
+ return Number.isFinite(n) ? n : null;
38
+ }
39
+ case 'date':
40
+ case 'select':
41
+ case 'textarea':
42
+ case 'text':
43
+ default:
44
+ return draft == null ? '' : String(draft);
45
+ }
46
+ }
47
+ export function draftFromValue(value, editor) {
48
+ if (editor.type === 'boolean')
49
+ return Boolean(value);
50
+ if (value == null)
51
+ return '';
52
+ if (value instanceof Date) {
53
+ return value.toISOString().slice(0, 10);
54
+ }
55
+ if (editor.type === 'date' && typeof value === 'string') {
56
+ return value.slice(0, 10);
57
+ }
58
+ return String(value);
59
+ }
@@ -0,0 +1,11 @@
1
+ import type { ConditionalFormatRule, ConditionalFormatStyle, FormatCondition } from './types.js';
2
+ export declare function evaluateCondition(row: Record<string, unknown>, when: FormatCondition): boolean;
3
+ export declare function styleToCss(style: ConditionalFormatStyle): string;
4
+ /**
5
+ * Returns merged styles for a row and per-column cell overrides.
6
+ * Higher priority wins; among equals, later rules win.
7
+ */
8
+ export declare function evaluateFormatRules(row: Record<string, unknown>, rules: ConditionalFormatRule[]): {
9
+ rowStyle: ConditionalFormatStyle;
10
+ cellStyles: Record<string, ConditionalFormatStyle>;
11
+ };
@@ -0,0 +1,98 @@
1
+ function getPathValue(row, path) {
2
+ return path.split('.').reduce((acc, part) => {
3
+ if (acc && typeof acc === 'object' && part in acc) {
4
+ return acc[part];
5
+ }
6
+ return undefined;
7
+ }, row);
8
+ }
9
+ function toNumber(value) {
10
+ if (typeof value === 'number' && !Number.isNaN(value))
11
+ return value;
12
+ if (typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Number(value))) {
13
+ return Number(value);
14
+ }
15
+ return null;
16
+ }
17
+ export function evaluateCondition(row, when) {
18
+ const raw = getPathValue(row, when.columnId);
19
+ switch (when.op) {
20
+ case 'empty':
21
+ return raw == null || raw === '';
22
+ case 'notEmpty':
23
+ return raw != null && raw !== '';
24
+ case 'eq':
25
+ return raw === when.value || String(raw) === String(when.value);
26
+ case 'neq':
27
+ return raw !== when.value && String(raw) !== String(when.value);
28
+ case 'contains':
29
+ return String(raw ?? '')
30
+ .toLowerCase()
31
+ .includes(String(when.value).toLowerCase());
32
+ case 'startsWith':
33
+ return String(raw ?? '')
34
+ .toLowerCase()
35
+ .startsWith(String(when.value).toLowerCase());
36
+ case 'gt':
37
+ case 'gte':
38
+ case 'lt':
39
+ case 'lte': {
40
+ const n = toNumber(raw);
41
+ const v = toNumber(when.value);
42
+ if (n == null || v == null)
43
+ return false;
44
+ if (when.op === 'gt')
45
+ return n > v;
46
+ if (when.op === 'gte')
47
+ return n >= v;
48
+ if (when.op === 'lt')
49
+ return n < v;
50
+ return n <= v;
51
+ }
52
+ case 'between': {
53
+ const n = toNumber(raw);
54
+ if (n == null)
55
+ return false;
56
+ return n >= when.min && n <= when.max;
57
+ }
58
+ default:
59
+ return false;
60
+ }
61
+ }
62
+ export function styleToCss(style) {
63
+ const parts = [];
64
+ if (style.background)
65
+ parts.push(`background-color:${style.background}`);
66
+ if (style.color)
67
+ parts.push(`color:${style.color}`);
68
+ if (style.fontWeight)
69
+ parts.push(`font-weight:${style.fontWeight}`);
70
+ if (style.border)
71
+ parts.push(`box-shadow:inset 0 0 0 1px ${style.border}`);
72
+ return parts.join(';');
73
+ }
74
+ /**
75
+ * Returns merged styles for a row and per-column cell overrides.
76
+ * Higher priority wins; among equals, later rules win.
77
+ */
78
+ export function evaluateFormatRules(row, rules) {
79
+ const enabled = [...rules]
80
+ .filter((r) => r.enabled)
81
+ .sort((a, b) => a.priority - b.priority);
82
+ let rowStyle = {};
83
+ const cellStyles = {};
84
+ for (const rule of enabled) {
85
+ if (!evaluateCondition(row, rule.when))
86
+ continue;
87
+ if (rule.target === 'row') {
88
+ rowStyle = { ...rowStyle, ...rule.style };
89
+ }
90
+ else if (rule.columnId) {
91
+ cellStyles[rule.columnId] = {
92
+ ...(cellStyles[rule.columnId] ?? {}),
93
+ ...rule.style
94
+ };
95
+ }
96
+ }
97
+ return { rowStyle, cellStyles };
98
+ }
@@ -0,0 +1,5 @@
1
+ import type { DataGridColumn, DataGridFilter } from './types.js';
2
+ export declare function cellText(row: Record<string, unknown>, column: DataGridColumn): string;
3
+ /** Client-side search + equality/contains filters. */
4
+ export declare function filterRows<T extends Record<string, unknown>>(rows: T[], columns: DataGridColumn<T>[], query: string, filters: DataGridFilter[]): T[];
5
+ export declare function uniqueColumnValues<T extends Record<string, unknown>>(rows: T[], column: DataGridColumn<T>, limit?: number): string[];
@@ -0,0 +1,60 @@
1
+ function getByPath(row, path) {
2
+ return path.split('.').reduce((acc, part) => {
3
+ if (acc && typeof acc === 'object' && part in acc) {
4
+ return acc[part];
5
+ }
6
+ return undefined;
7
+ }, row);
8
+ }
9
+ export function cellText(row, column) {
10
+ const key = String(column.accessor ?? column.id);
11
+ const value = getByPath(row, key);
12
+ if (value == null)
13
+ return '';
14
+ if (typeof value === 'boolean')
15
+ return value ? 'Yes' : 'No';
16
+ return String(value);
17
+ }
18
+ /** Client-side search + equality/contains filters. */
19
+ export function filterRows(rows, columns, query, filters) {
20
+ const q = query.trim().toLowerCase();
21
+ return rows.filter((row) => {
22
+ const record = row;
23
+ if (q) {
24
+ const hit = columns.some((col) => cellText(record, col).toLowerCase().includes(q));
25
+ if (!hit)
26
+ return false;
27
+ }
28
+ for (const f of filters) {
29
+ const col = columns.find((c) => c.id === f.columnId);
30
+ if (!col)
31
+ continue;
32
+ const text = cellText(record, col).toLowerCase();
33
+ const needle = f.value.trim().toLowerCase();
34
+ if (!needle)
35
+ continue;
36
+ if (f.op === 'eq') {
37
+ if (text !== needle)
38
+ return false;
39
+ }
40
+ else if (!text.includes(needle)) {
41
+ return false;
42
+ }
43
+ }
44
+ return true;
45
+ });
46
+ }
47
+ export function uniqueColumnValues(rows, column, limit = 24) {
48
+ const seen = new Set();
49
+ const out = [];
50
+ for (const row of rows) {
51
+ const text = cellText(row, column);
52
+ if (!text || seen.has(text))
53
+ continue;
54
+ seen.add(text);
55
+ out.push(text);
56
+ if (out.length >= limit)
57
+ break;
58
+ }
59
+ return out.sort((a, b) => a.localeCompare(b));
60
+ }
@@ -0,0 +1,9 @@
1
+ import type { MarkColor, MarkPreset } from './types.js';
2
+ export declare const MARK_COLORS: MarkPreset[];
3
+ export declare const MARK_TINT: Record<MarkPreset, string>;
4
+ export declare const MARK_SWATCH: Record<MarkPreset, string>;
5
+ export declare function isMarkPreset(color: string): color is MarkPreset;
6
+ /** Resolve a mark color (preset name or custom CSS color) to a soft background tint. */
7
+ export declare function markTint(color: MarkColor): string;
8
+ /** Resolve a mark color to a solid swatch for the picker UI. */
9
+ export declare function markSwatch(color: MarkColor): string;
@@ -0,0 +1,91 @@
1
+ export const MARK_COLORS = [
2
+ 'amber',
3
+ 'rose',
4
+ 'sky',
5
+ 'emerald',
6
+ 'violet',
7
+ 'orange',
8
+ 'lime',
9
+ 'cyan',
10
+ 'fuchsia',
11
+ 'slate',
12
+ 'pink',
13
+ 'indigo'
14
+ ];
15
+ export const MARK_TINT = {
16
+ amber: 'rgba(245, 158, 11, 0.18)',
17
+ rose: 'rgba(244, 63, 94, 0.16)',
18
+ sky: 'rgba(14, 165, 233, 0.16)',
19
+ emerald: 'rgba(16, 185, 129, 0.16)',
20
+ violet: 'rgba(139, 92, 246, 0.16)',
21
+ orange: 'rgba(249, 115, 22, 0.18)',
22
+ lime: 'rgba(132, 204, 22, 0.18)',
23
+ cyan: 'rgba(6, 182, 212, 0.16)',
24
+ fuchsia: 'rgba(217, 70, 239, 0.16)',
25
+ slate: 'rgba(100, 116, 139, 0.2)',
26
+ pink: 'rgba(236, 72, 153, 0.16)',
27
+ indigo: 'rgba(99, 102, 241, 0.16)'
28
+ };
29
+ export const MARK_SWATCH = {
30
+ amber: '#f59e0b',
31
+ rose: '#f43f5e',
32
+ sky: '#0ea5e9',
33
+ emerald: '#10b981',
34
+ violet: '#8b5cf6',
35
+ orange: '#f97316',
36
+ lime: '#84cc16',
37
+ cyan: '#06b6d4',
38
+ fuchsia: '#d946ef',
39
+ slate: '#64748b',
40
+ pink: '#ec4899',
41
+ indigo: '#6366f1'
42
+ };
43
+ const PRESET_SET = new Set(MARK_COLORS);
44
+ export function isMarkPreset(color) {
45
+ return PRESET_SET.has(color);
46
+ }
47
+ /** Resolve a mark color (preset name or custom CSS color) to a soft background tint. */
48
+ export function markTint(color) {
49
+ if (isMarkPreset(color))
50
+ return MARK_TINT[color];
51
+ const rgb = parseCssColor(color);
52
+ if (!rgb)
53
+ return color;
54
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.18)`;
55
+ }
56
+ /** Resolve a mark color to a solid swatch for the picker UI. */
57
+ export function markSwatch(color) {
58
+ if (isMarkPreset(color))
59
+ return MARK_SWATCH[color];
60
+ return color;
61
+ }
62
+ function parseCssColor(input) {
63
+ const s = input.trim();
64
+ if (!s)
65
+ return null;
66
+ if (s.startsWith('#')) {
67
+ const hex = s.slice(1);
68
+ if (hex.length === 3) {
69
+ const r = parseInt(hex[0] + hex[0], 16);
70
+ const g = parseInt(hex[1] + hex[1], 16);
71
+ const b = parseInt(hex[2] + hex[2], 16);
72
+ if ([r, g, b].some((n) => Number.isNaN(n)))
73
+ return null;
74
+ return { r, g, b };
75
+ }
76
+ if (hex.length === 6 || hex.length === 8) {
77
+ const r = parseInt(hex.slice(0, 2), 16);
78
+ const g = parseInt(hex.slice(2, 4), 16);
79
+ const b = parseInt(hex.slice(4, 6), 16);
80
+ if ([r, g, b].some((n) => Number.isNaN(n)))
81
+ return null;
82
+ return { r, g, b };
83
+ }
84
+ return null;
85
+ }
86
+ const rgb = s.match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*[\d.]+\s*)?\)$/i);
87
+ if (rgb) {
88
+ return { r: Number(rgb[1]), g: Number(rgb[2]), b: Number(rgb[3]) };
89
+ }
90
+ return null;
91
+ }
@@ -0,0 +1,126 @@
1
+ export interface DataGridColumn<Row = Record<string, unknown>> {
2
+ id: string;
3
+ header: string;
4
+ /** Dot-path key on the row, or custom render via `cell` snippet. */
5
+ accessor?: keyof Row | string;
6
+ align?: 'left' | 'center' | 'right';
7
+ sortable?: boolean;
8
+ width?: string;
9
+ minWidth?: string;
10
+ pinned?: boolean;
11
+ hidden?: boolean;
12
+ /**
13
+ * Auto-hide this column below the breakpoint (still available in row collapse
14
+ * and non-table view modes as secondary fields).
15
+ */
16
+ hideBelow?: Breakpoint;
17
+ /** Include in FilterBar quick-filter dropdown. */
18
+ filterable?: boolean;
19
+ editable?: boolean;
20
+ /** Typed inline editor. When omitted, inferred from the cell value. */
21
+ edit?: DataGridEditConfig;
22
+ class?: string;
23
+ /** Free-form metadata for consumers / ResourceStudio */
24
+ meta?: Record<string, unknown>;
25
+ }
26
+ export type Breakpoint = 'sm' | 'md' | 'lg' | 'xl';
27
+ export type DataGridViewMode = 'table' | 'list' | 'card' | 'grid';
28
+ export interface DataGridFilter {
29
+ id: string;
30
+ columnId: string;
31
+ value: string;
32
+ /** Default `contains`. */
33
+ op?: 'contains' | 'eq';
34
+ label?: string;
35
+ }
36
+ export type DataGridEditType = 'text' | 'number' | 'textarea' | 'boolean' | 'select' | 'date';
37
+ export interface DataGridEditOption {
38
+ value: string;
39
+ label: string;
40
+ disabled?: boolean;
41
+ }
42
+ export interface DataGridEditConfig {
43
+ type: DataGridEditType;
44
+ /** For `select` */
45
+ options?: DataGridEditOption[];
46
+ placeholder?: string;
47
+ min?: number;
48
+ max?: number;
49
+ step?: number;
50
+ }
51
+ export interface CellRef {
52
+ rowId: string;
53
+ columnId: string;
54
+ }
55
+ export type GridSelection = {
56
+ type: 'none';
57
+ } | {
58
+ type: 'rows';
59
+ ids: string[];
60
+ } | {
61
+ type: 'columns';
62
+ ids: string[];
63
+ } | {
64
+ type: 'cells';
65
+ cells: CellRef[];
66
+ };
67
+ export interface CellNote {
68
+ rowId: string;
69
+ columnId: string;
70
+ text: string;
71
+ author?: string;
72
+ updatedAt?: string;
73
+ }
74
+ export type MarkPreset = 'amber' | 'rose' | 'sky' | 'emerald' | 'violet' | 'orange' | 'lime' | 'cyan' | 'fuchsia' | 'slate' | 'pink' | 'indigo';
75
+ /** Named preset or any CSS color string (e.g. `#ff5500`). */
76
+ export type MarkColor = MarkPreset | (string & {});
77
+ export interface GridMark {
78
+ rowId: string;
79
+ /** Present = cell mark; absent = whole-row mark */
80
+ columnId?: string;
81
+ color: MarkColor;
82
+ }
83
+ export type FormatTarget = 'row' | 'cell';
84
+ export type FormatCondition = {
85
+ op: 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte';
86
+ columnId: string;
87
+ value: string | number | boolean;
88
+ } | {
89
+ op: 'contains' | 'startsWith';
90
+ columnId: string;
91
+ value: string;
92
+ } | {
93
+ op: 'empty' | 'notEmpty';
94
+ columnId: string;
95
+ } | {
96
+ op: 'between';
97
+ columnId: string;
98
+ min: number;
99
+ max: number;
100
+ };
101
+ export interface ConditionalFormatStyle {
102
+ background?: string;
103
+ color?: string;
104
+ fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';
105
+ border?: string;
106
+ }
107
+ export interface ConditionalFormatRule {
108
+ id: string;
109
+ name?: string;
110
+ enabled: boolean;
111
+ target: FormatTarget;
112
+ /** Required when target === 'cell' */
113
+ columnId?: string;
114
+ when: FormatCondition;
115
+ style: ConditionalFormatStyle;
116
+ priority: number;
117
+ }
118
+ export type SortDir = 'asc' | 'desc' | null;
119
+ export declare const EMPTY_SELECTION: GridSelection;
120
+ export declare function noteKey(rowId: string, columnId: string): string;
121
+ export declare function markKey(rowId: string, columnId?: string): string;
122
+ export declare function selectionCount(selection: GridSelection): number;
123
+ export declare function selectionLabel(selection: GridSelection): {
124
+ itemLabel: string;
125
+ itemLabelPlural: string;
126
+ };
@@ -0,0 +1,21 @@
1
+ export const EMPTY_SELECTION = { type: 'none' };
2
+ export function noteKey(rowId, columnId) {
3
+ return `${rowId}::${columnId}`;
4
+ }
5
+ export function markKey(rowId, columnId) {
6
+ return columnId ? `${rowId}::${columnId}` : `${rowId}::*`;
7
+ }
8
+ export function selectionCount(selection) {
9
+ if (selection.type === 'none')
10
+ return 0;
11
+ if (selection.type === 'rows' || selection.type === 'columns')
12
+ return selection.ids.length;
13
+ return selection.cells.length;
14
+ }
15
+ export function selectionLabel(selection) {
16
+ if (selection.type === 'columns')
17
+ return { itemLabel: 'column', itemLabelPlural: 'columns' };
18
+ if (selection.type === 'cells')
19
+ return { itemLabel: 'cell', itemLabelPlural: 'cells' };
20
+ return { itemLabel: 'row', itemLabelPlural: 'rows' };
21
+ }
@@ -0,0 +1,33 @@
1
+ import type { StoryObj } from '@storybook/svelte';
2
+ declare const meta: {
3
+ title: string;
4
+ component: import("svelte").Component<{
5
+ example?: "loading" | "readOnly" | "empty" | "permissions" | "crudAdmin" | "cms" | "sqlBrowser" | "customQuery" | "notesAndRules" | "bulkWorkflow" | "mainOnly";
6
+ }, {}, "">;
7
+ tags: string[];
8
+ argTypes: {
9
+ example: {
10
+ control: "select";
11
+ options: string[];
12
+ };
13
+ };
14
+ args: {
15
+ example: "crudAdmin";
16
+ };
17
+ parameters: {
18
+ layout: string;
19
+ };
20
+ };
21
+ export default meta;
22
+ type Story = StoryObj<typeof meta>;
23
+ export declare const CrudAdmin: Story;
24
+ export declare const CmsCollections: Story;
25
+ export declare const ReadOnlyCatalog: Story;
26
+ export declare const SqlBrowser: Story;
27
+ export declare const CustomQuerySlot: Story;
28
+ export declare const WithNotesAndRules: Story;
29
+ export declare const BulkWorkflow: Story;
30
+ export declare const EmptyAndLoading: Story;
31
+ export declare const Loading: Story;
32
+ export declare const MainOnly: Story;
33
+ export declare const PermissionsGated: Story;
@@ -0,0 +1,56 @@
1
+ import ResourceStudioStory from './ResourceStudioStory.svelte';
2
+ const meta = {
3
+ title: 'Organisms/ResourceStudio',
4
+ component: ResourceStudioStory,
5
+ tags: ['autodocs'],
6
+ argTypes: {
7
+ example: {
8
+ control: 'select',
9
+ options: [
10
+ 'crudAdmin',
11
+ 'cms',
12
+ 'readOnly',
13
+ 'sqlBrowser',
14
+ 'customQuery',
15
+ 'notesAndRules',
16
+ 'bulkWorkflow',
17
+ 'empty',
18
+ 'loading',
19
+ 'mainOnly',
20
+ 'permissions'
21
+ ]
22
+ }
23
+ },
24
+ args: { example: 'crudAdmin' },
25
+ parameters: { layout: 'fullscreen' }
26
+ };
27
+ export default meta;
28
+ export const CrudAdmin = {};
29
+ export const CmsCollections = { args: { example: 'cms' } };
30
+ export const ReadOnlyCatalog = { args: { example: 'readOnly' } };
31
+ export const SqlBrowser = { args: { example: 'sqlBrowser' } };
32
+ export const CustomQuerySlot = { args: { example: 'customQuery' } };
33
+ export const WithNotesAndRules = {
34
+ args: { example: 'notesAndRules' },
35
+ parameters: {
36
+ docs: {
37
+ description: {
38
+ story: 'Orders with cell notes, row/cell conditional format rules, and the Rules panel open from the toolbar.'
39
+ }
40
+ }
41
+ }
42
+ };
43
+ export const BulkWorkflow = {
44
+ args: { example: 'bulkWorkflow' },
45
+ parameters: {
46
+ docs: {
47
+ description: {
48
+ story: 'Ops queue: rows pre-selected, dock shows Approve / Reject / Assign, plus an Activity tab for the workflow.'
49
+ }
50
+ }
51
+ }
52
+ };
53
+ export const EmptyAndLoading = { args: { example: 'empty' } };
54
+ export const Loading = { args: { example: 'loading' } };
55
+ export const MainOnly = { args: { example: 'mainOnly' } };
56
+ export const PermissionsGated = { args: { example: 'permissions' } };