@stratum-hq/react 0.1.0 → 0.2.1

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 (55) hide show
  1. package/dist/components/AuditLogViewer.d.ts +6 -0
  2. package/dist/components/AuditLogViewer.d.ts.map +1 -0
  3. package/dist/components/AuditLogViewer.js +42 -0
  4. package/dist/components/AuditLogViewer.js.map +1 -0
  5. package/dist/components/ConfigInheritanceVisualizer.d.ts +17 -0
  6. package/dist/components/ConfigInheritanceVisualizer.d.ts.map +1 -0
  7. package/dist/components/ConfigInheritanceVisualizer.js +353 -0
  8. package/dist/components/ConfigInheritanceVisualizer.js.map +1 -0
  9. package/dist/components/DraggableTenantTree.d.ts +31 -0
  10. package/dist/components/DraggableTenantTree.d.ts.map +1 -0
  11. package/dist/components/DraggableTenantTree.js +214 -0
  12. package/dist/components/DraggableTenantTree.js.map +1 -0
  13. package/dist/components/TenantTree.d.ts +4 -1
  14. package/dist/components/TenantTree.d.ts.map +1 -1
  15. package/dist/components/TenantTree.js +4 -4
  16. package/dist/components/TenantTree.js.map +1 -1
  17. package/dist/components/WebhookEditor.d.ts +5 -0
  18. package/dist/components/WebhookEditor.d.ts.map +1 -0
  19. package/dist/components/WebhookEditor.js +60 -0
  20. package/dist/components/WebhookEditor.js.map +1 -0
  21. package/dist/components/headless/ConfigEditor.d.ts +0 -1
  22. package/dist/components/headless/ConfigEditor.d.ts.map +1 -1
  23. package/dist/components/headless/ConfigInheritanceVisualizer.d.ts +17 -0
  24. package/dist/components/headless/ConfigInheritanceVisualizer.d.ts.map +1 -0
  25. package/dist/components/headless/ConfigInheritanceVisualizer.js +7 -0
  26. package/dist/components/headless/ConfigInheritanceVisualizer.js.map +1 -0
  27. package/dist/components/headless/PermissionEditor.d.ts +0 -1
  28. package/dist/components/headless/PermissionEditor.d.ts.map +1 -1
  29. package/dist/components/headless/TenantSwitcher.d.ts +0 -1
  30. package/dist/components/headless/TenantSwitcher.d.ts.map +1 -1
  31. package/dist/components/headless/TenantTree.d.ts +0 -1
  32. package/dist/components/headless/TenantTree.d.ts.map +1 -1
  33. package/dist/hooks/use-audit-logs.d.ts +20 -0
  34. package/dist/hooks/use-audit-logs.d.ts.map +1 -0
  35. package/dist/hooks/use-audit-logs.js +29 -0
  36. package/dist/hooks/use-audit-logs.js.map +1 -0
  37. package/dist/hooks/use-config-cascade.d.ts +39 -0
  38. package/dist/hooks/use-config-cascade.d.ts.map +1 -0
  39. package/dist/hooks/use-config-cascade.js +82 -0
  40. package/dist/hooks/use-config-cascade.js.map +1 -0
  41. package/dist/hooks/use-messages.d.ts.map +1 -1
  42. package/dist/hooks/use-tenant-tree.d.ts.map +1 -1
  43. package/dist/hooks/use-tenant-tree.js +34 -4
  44. package/dist/hooks/use-tenant-tree.js.map +1 -1
  45. package/dist/hooks/use-tenant.d.ts +1 -0
  46. package/dist/hooks/use-tenant.d.ts.map +1 -1
  47. package/dist/hooks/use-webhooks.d.ts +24 -0
  48. package/dist/hooks/use-webhooks.d.ts.map +1 -0
  49. package/dist/hooks/use-webhooks.js +46 -0
  50. package/dist/hooks/use-webhooks.js.map +1 -0
  51. package/dist/index.d.ts +16 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +8 -0
  54. package/dist/index.js.map +1 -1
  55. package/package.json +4 -2
@@ -0,0 +1,6 @@
1
+ export interface AuditLogViewerProps {
2
+ limit?: number;
3
+ className?: string;
4
+ }
5
+ export declare function AuditLogViewer({ limit, className }: AuditLogViewerProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=AuditLogViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogViewer.d.ts","sourceRoot":"","sources":["../../src/components/AuditLogViewer.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD,wBAAgB,cAAc,CAAC,EAAE,KAAU,EAAE,SAAS,EAAE,EAAE,mBAAmB,2CAyD5E"}
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuditLogs } from "../hooks/use-audit-logs.js";
3
+ import { TableSkeleton } from "./TableSkeleton.js";
4
+ const ACTION_VARIANTS = {
5
+ "tenant.created": "stratum-badge--own",
6
+ "tenant.updated": "stratum-badge--inherited",
7
+ "tenant.deleted": "stratum-badge--locked",
8
+ "tenant.moved": "stratum-badge--inherited",
9
+ "tenant.reordered": "stratum-badge--inherited",
10
+ "config.updated": "stratum-badge--inherited",
11
+ "config.deleted": "stratum-badge--locked",
12
+ "permission.created": "stratum-badge--own",
13
+ "permission.deleted": "stratum-badge--locked",
14
+ };
15
+ function formatTime(iso) {
16
+ try {
17
+ const d = new Date(iso);
18
+ const now = Date.now();
19
+ const diff = now - d.getTime();
20
+ if (diff < 60_000)
21
+ return "just now";
22
+ if (diff < 3_600_000)
23
+ return `${Math.floor(diff / 60_000)}m ago`;
24
+ if (diff < 86_400_000)
25
+ return `${Math.floor(diff / 3_600_000)}h ago`;
26
+ return d.toLocaleDateString();
27
+ }
28
+ catch {
29
+ return iso;
30
+ }
31
+ }
32
+ export function AuditLogViewer({ limit = 20, className }) {
33
+ const { entries, loading, error } = useAuditLogs(limit);
34
+ if (loading) {
35
+ return (_jsx("div", { className: `stratum-audit-viewer ${className || ""}`, children: _jsx(TableSkeleton, { rows: 5, columns: 4 }) }));
36
+ }
37
+ if (error) {
38
+ return _jsxs("div", { className: className, children: ["Failed to load audit logs: ", error.message] });
39
+ }
40
+ return (_jsx("div", { className: `stratum-audit-viewer ${className || ""}`, children: _jsxs("table", { className: "stratum-audit-viewer__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Action" }), _jsx("th", { children: "Resource" }), _jsx("th", { children: "Actor" }), _jsx("th", { children: "Time" })] }) }), _jsxs("tbody", { children: [entries.map((entry) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("span", { className: `stratum-badge ${ACTION_VARIANTS[entry.action] || ""}`, children: entry.action }) }), _jsx("td", { children: entry.resource_type && (_jsxs("span", { children: [entry.resource_type, entry.resource_id && _jsxs("code", { children: [" ", entry.resource_id.slice(0, 8), "..."] })] })) }), _jsx("td", { children: entry.actor || "system" }), _jsx("td", { children: formatTime(entry.created_at) })] }, entry.id))), entries.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 4, style: { textAlign: "center", padding: "16px" }, children: "No audit entries yet. Actions will appear here as you use the platform." }) }))] })] }) }));
41
+ }
42
+ //# sourceMappingURL=AuditLogViewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuditLogViewer.js","sourceRoot":"","sources":["../../src/components/AuditLogViewer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * ConfigInheritanceVisualizer — shows how config values cascade from
3
+ * parent to children with real-time visual feedback.
4
+ *
5
+ * ┌─────────────────────────┐ ┌─────────────────────────┐
6
+ * │ Parent: AcmeSec │ │ Child: NorthStar MSP │
7
+ * │ ─────────────────────── │ ──▶ │ ─────────────────────── │
8
+ * │ max_users 1000 │ │ max_users 500 own │
9
+ * │ api_rate 10000 🔒 │ │ api_rate 10000 ↑ │
10
+ * │ brand_color #2563EB │ │ brand_color #1E40AF │
11
+ * └─────────────────────────┘ └─────────────────────────┘
12
+ */
13
+ export interface ConfigInheritanceVisualizerProps {
14
+ className?: string;
15
+ }
16
+ export declare function ConfigInheritanceVisualizer({ className }: ConfigInheritanceVisualizerProps): import("react/jsx-runtime").JSX.Element | null;
17
+ //# sourceMappingURL=ConfigInheritanceVisualizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigInheritanceVisualizer.d.ts","sourceRoot":"","sources":["../../src/components/ConfigInheritanceVisualizer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,WAAW,gCAAgC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2ED,wBAAgB,2BAA2B,CAAC,EAAE,SAAS,EAAE,EAAE,gCAAgC,kDA6H1F"}
@@ -0,0 +1,353 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * ConfigInheritanceVisualizer — shows how config values cascade from
4
+ * parent to children with real-time visual feedback.
5
+ *
6
+ * ┌─────────────────────────┐ ┌─────────────────────────┐
7
+ * │ Parent: AcmeSec │ │ Child: NorthStar MSP │
8
+ * │ ─────────────────────── │ ──▶ │ ─────────────────────── │
9
+ * │ max_users 1000 │ │ max_users 500 own │
10
+ * │ api_rate 10000 🔒 │ │ api_rate 10000 ↑ │
11
+ * │ brand_color #2563EB │ │ brand_color #1E40AF │
12
+ * └─────────────────────────┘ └─────────────────────────┘
13
+ */
14
+ import { useState } from "react";
15
+ import { useConfigCascade } from "../hooks/use-config-cascade.js";
16
+ import { TableSkeleton } from "./TableSkeleton.js";
17
+ function Badge({ type }) {
18
+ const styles = {
19
+ inherited: { label: "Inherited", icon: "\u2191", className: "stratum-cascade-badge--inherited" },
20
+ locked: { label: "Locked", icon: "\u2193", className: "stratum-cascade-badge--locked" },
21
+ own: { label: "Own", icon: "\u2022", className: "stratum-cascade-badge--own" },
22
+ };
23
+ const s = styles[type];
24
+ return (_jsxs("span", { className: `stratum-cascade-badge ${s.className}`, children: [s.icon, " ", s.label] }));
25
+ }
26
+ function getBadgeType(entry) {
27
+ if (entry.locked)
28
+ return "locked";
29
+ if (entry.inherited)
30
+ return "inherited";
31
+ return "own";
32
+ }
33
+ function ConfigTable({ entries, title, subtitle, highlightKey, }) {
34
+ return (_jsxs("div", { className: "stratum-cascade-panel", children: [_jsxs("div", { className: "stratum-cascade-panel__header", children: [_jsx("span", { className: "stratum-cascade-panel__title", children: title }), subtitle && _jsx("span", { className: "stratum-cascade-panel__subtitle", children: subtitle })] }), _jsxs("table", { className: "stratum-cascade-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Key" }), _jsx("th", { children: "Value" }), _jsx("th", { children: "Status" })] }) }), _jsxs("tbody", { children: [entries.map((entry) => (_jsxs("tr", { className: highlightKey === entry.key ? "stratum-cascade-row--highlight" : "", children: [_jsx("td", { className: "stratum-cascade-key", children: entry.key }), _jsx("td", { className: "stratum-cascade-value", children: _jsx("code", { children: JSON.stringify(entry.value) }) }), _jsx("td", { children: _jsx(Badge, { type: getBadgeType(entry) }) })] }, entry.key))), entries.length === 0 && (_jsx("tr", { children: _jsx("td", { colSpan: 3, className: "stratum-cascade-empty", children: "No config values" }) }))] })] })] }));
35
+ }
36
+ export function ConfigInheritanceVisualizer({ className }) {
37
+ const { data, loading, error, refresh } = useConfigCascade();
38
+ const [selectedChild, setSelectedChild] = useState(0);
39
+ const [highlightKey, setHighlightKey] = useState(null);
40
+ if (loading) {
41
+ return (_jsx("div", { className: `stratum-cascade ${className || ""}`, children: _jsx(TableSkeleton, { rows: 4, columns: 3 }) }));
42
+ }
43
+ if (error) {
44
+ return (_jsxs("div", { className: `stratum-cascade stratum-cascade--error ${className || ""}`, children: [_jsxs("p", { children: ["Failed to load inheritance data: ", error.message] }), _jsx("button", { type: "button", onClick: refresh, className: "stratum-cascade-retry", children: "Retry" })] }));
45
+ }
46
+ if (!data)
47
+ return null;
48
+ const activeChild = data.children[selectedChild];
49
+ return (_jsxs("div", { className: `stratum-cascade ${className || ""}`, children: [_jsx("style", { children: cascadeStyles }), data.children.length > 1 && (_jsx("div", { className: "stratum-cascade-tabs", role: "tablist", children: data.children.map((child, i) => (_jsx("button", { role: "tab", "aria-selected": i === selectedChild, className: `stratum-cascade-tab${i === selectedChild ? " active" : ""}`, onClick: () => { setSelectedChild(i); setHighlightKey(null); }, children: child.name }, child.id))) })), _jsxs("div", { className: "stratum-cascade-split", children: [_jsx(ConfigTable, { entries: data.parent.config, title: data.parent.name, subtitle: "Parent", highlightKey: highlightKey }), _jsxs("div", { className: "stratum-cascade-arrow", "aria-hidden": "true", children: [_jsx("div", { className: "stratum-cascade-arrow__line" }), _jsx("div", { className: "stratum-cascade-arrow__head", children: "\u25B6" })] }), activeChild ? (_jsx(ConfigTable, { entries: activeChild.config, title: activeChild.name, subtitle: "Child", highlightKey: highlightKey })) : (_jsxs("div", { className: "stratum-cascade-panel stratum-cascade-panel--empty", children: [_jsx("div", { className: "stratum-cascade-panel__header", children: _jsx("span", { className: "stratum-cascade-panel__title", children: "No children" }) }), _jsx("p", { className: "stratum-cascade-empty-message", children: "This tenant has no child tenants. Create a child tenant to see config inheritance in action." })] }))] }), activeChild && (_jsxs("div", { className: "stratum-cascade-diff", children: [_jsx("span", { className: "stratum-cascade-diff__label", children: "Inheritance summary:" }), (() => {
50
+ const inherited = activeChild.config.filter((e) => e.inherited && !e.locked).length;
51
+ const locked = activeChild.config.filter((e) => e.locked).length;
52
+ const own = activeChild.config.filter((e) => !e.inherited && !e.locked).length;
53
+ return (_jsxs(_Fragment, { children: [inherited > 0 && (_jsxs("span", { className: "stratum-cascade-diff__stat stratum-cascade-diff__stat--inherited", onMouseEnter: () => {
54
+ const firstInherited = activeChild.config.find((e) => e.inherited && !e.locked);
55
+ if (firstInherited)
56
+ setHighlightKey(firstInherited.key);
57
+ }, onMouseLeave: () => setHighlightKey(null), children: [inherited, " inherited"] })), locked > 0 && (_jsxs("span", { className: "stratum-cascade-diff__stat stratum-cascade-diff__stat--locked", children: [locked, " locked"] })), own > 0 && (_jsxs("span", { className: "stratum-cascade-diff__stat stratum-cascade-diff__stat--own", children: [own, " overridden"] }))] }));
58
+ })()] }))] }));
59
+ }
60
+ // ── Scoped styles ─────────────────────────────────────────────
61
+ const cascadeStyles = `
62
+ .stratum-cascade {
63
+ font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
64
+ }
65
+
66
+ .stratum-cascade--error {
67
+ padding: var(--space-xl, 24px);
68
+ color: var(--color-error, #DC2626);
69
+ font-size: 0.875rem;
70
+ }
71
+
72
+ .stratum-cascade-retry {
73
+ margin-top: var(--space-sm, 8px);
74
+ padding: var(--space-xs, 4px) var(--space-md, 12px);
75
+ border: 1px solid var(--border, #E2E8F0);
76
+ border-radius: var(--radius-sm, 4px);
77
+ background: var(--bg-card, white);
78
+ color: var(--text-secondary, #475569);
79
+ cursor: pointer;
80
+ font-size: 0.75rem;
81
+ }
82
+
83
+ /* Child selector tabs */
84
+ .stratum-cascade-tabs {
85
+ display: flex;
86
+ gap: 0;
87
+ border-bottom: 1px solid var(--border, #E2E8F0);
88
+ margin-bottom: var(--space-lg, 16px);
89
+ overflow-x: auto;
90
+ }
91
+
92
+ .stratum-cascade-tab {
93
+ padding: var(--space-sm, 8px) var(--space-lg, 16px);
94
+ font-size: 0.75rem;
95
+ font-weight: 500;
96
+ color: var(--text-tertiary, #64748B);
97
+ background: transparent;
98
+ border: none;
99
+ border-bottom: 2px solid transparent;
100
+ cursor: pointer;
101
+ font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
102
+ white-space: nowrap;
103
+ }
104
+
105
+ .stratum-cascade-tab:hover {
106
+ color: var(--text-primary, #0F172A);
107
+ }
108
+
109
+ .stratum-cascade-tab.active {
110
+ color: var(--color-accent, #0D9488);
111
+ border-bottom-color: var(--color-accent, #0D9488);
112
+ }
113
+
114
+ /* Split-screen layout */
115
+ .stratum-cascade-split {
116
+ display: flex;
117
+ gap: var(--space-md, 12px);
118
+ align-items: flex-start;
119
+ }
120
+
121
+ /* Cascade arrow */
122
+ .stratum-cascade-arrow {
123
+ display: flex;
124
+ flex-direction: column;
125
+ align-items: center;
126
+ justify-content: center;
127
+ padding: var(--space-3xl, 48px) 0;
128
+ flex-shrink: 0;
129
+ color: var(--color-accent, #0D9488);
130
+ opacity: 0.6;
131
+ }
132
+
133
+ .stratum-cascade-arrow__line {
134
+ width: 2px;
135
+ height: 24px;
136
+ background: var(--color-accent, #0D9488);
137
+ opacity: 0.4;
138
+ }
139
+
140
+ .stratum-cascade-arrow__head {
141
+ font-size: 0.75rem;
142
+ transform: rotate(0deg);
143
+ }
144
+
145
+ /* Panel (each side of the split) */
146
+ .stratum-cascade-panel {
147
+ flex: 1;
148
+ min-width: 0;
149
+ border: 1px solid var(--border, #E2E8F0);
150
+ border-radius: var(--radius-md, 6px);
151
+ overflow: hidden;
152
+ }
153
+
154
+ .stratum-cascade-panel--empty {
155
+ display: flex;
156
+ flex-direction: column;
157
+ align-items: center;
158
+ justify-content: center;
159
+ min-height: 200px;
160
+ }
161
+
162
+ .stratum-cascade-panel__header {
163
+ padding: var(--space-sm, 8px) var(--space-md, 12px);
164
+ border-bottom: 1px solid var(--border, #E2E8F0);
165
+ background: var(--bg-card, white);
166
+ display: flex;
167
+ align-items: baseline;
168
+ gap: var(--space-sm, 8px);
169
+ }
170
+
171
+ .stratum-cascade-panel__title {
172
+ font-size: 0.8125rem;
173
+ font-weight: 700;
174
+ color: var(--text-primary, #0F172A);
175
+ font-family: var(--font-display, 'Satoshi', sans-serif);
176
+ }
177
+
178
+ .stratum-cascade-panel__subtitle {
179
+ font-size: 0.6875rem;
180
+ color: var(--text-tertiary, #64748B);
181
+ text-transform: uppercase;
182
+ letter-spacing: 0.05em;
183
+ }
184
+
185
+ .stratum-cascade-empty-message {
186
+ padding: var(--space-xl, 24px);
187
+ text-align: center;
188
+ color: var(--text-tertiary, #64748B);
189
+ font-size: 0.8125rem;
190
+ }
191
+
192
+ /* Config table within panel */
193
+ .stratum-cascade-table {
194
+ width: 100%;
195
+ border-collapse: collapse;
196
+ font-size: 0.75rem;
197
+ }
198
+
199
+ .stratum-cascade-table th {
200
+ padding: var(--space-xs, 4px) var(--space-md, 12px);
201
+ text-align: left;
202
+ font-weight: 600;
203
+ font-size: 0.625rem;
204
+ text-transform: uppercase;
205
+ letter-spacing: 0.06em;
206
+ color: var(--text-tertiary, #64748B);
207
+ border-bottom: 1px solid var(--border, #E2E8F0);
208
+ font-family: var(--font-mono, 'JetBrains Mono', monospace);
209
+ }
210
+
211
+ .stratum-cascade-table td {
212
+ padding: var(--space-xs, 4px) var(--space-md, 12px);
213
+ border-bottom: 1px solid var(--border, #E2E8F0);
214
+ color: var(--text-primary, #0F172A);
215
+ }
216
+
217
+ .stratum-cascade-key {
218
+ font-family: var(--font-mono, 'JetBrains Mono', monospace);
219
+ font-weight: 500;
220
+ }
221
+
222
+ .stratum-cascade-value code {
223
+ font-family: var(--font-mono, 'JetBrains Mono', monospace);
224
+ font-size: 0.6875rem;
225
+ color: var(--text-secondary, #475569);
226
+ }
227
+
228
+ .stratum-cascade-empty {
229
+ text-align: center;
230
+ color: var(--text-tertiary, #64748B);
231
+ padding: var(--space-lg, 16px) !important;
232
+ font-style: italic;
233
+ }
234
+
235
+ /* Highlight row on hover from diff summary */
236
+ .stratum-cascade-row--highlight {
237
+ background: rgba(13, 148, 136, 0.08);
238
+ }
239
+
240
+ /* Badges */
241
+ .stratum-cascade-badge {
242
+ display: inline-flex;
243
+ align-items: center;
244
+ gap: 2px;
245
+ font-size: 0.625rem;
246
+ font-weight: 600;
247
+ padding: 1px 6px;
248
+ border-radius: 9999px;
249
+ white-space: nowrap;
250
+ }
251
+
252
+ .stratum-cascade-badge--inherited {
253
+ color: var(--color-accent, #0D9488);
254
+ background: var(--color-accent-light, #CCFBF1);
255
+ }
256
+
257
+ .stratum-cascade-badge--locked {
258
+ color: var(--color-warning, #D97706);
259
+ background: var(--color-warning-bg, #FEF3C7);
260
+ }
261
+
262
+ .stratum-cascade-badge--own {
263
+ color: var(--text-secondary, #475569);
264
+ background: var(--bg-input, var(--color-100, #F1F5F9));
265
+ border: 1px solid var(--border, #E2E8F0);
266
+ }
267
+
268
+ /* Dark mode overrides */
269
+ [data-theme="dark"] .stratum-cascade-badge--inherited {
270
+ background: rgba(13, 148, 136, 0.15);
271
+ }
272
+
273
+ [data-theme="dark"] .stratum-cascade-badge--locked {
274
+ background: rgba(217, 119, 6, 0.15);
275
+ }
276
+
277
+ /* Diff summary bar */
278
+ .stratum-cascade-diff {
279
+ margin-top: var(--space-md, 12px);
280
+ padding: var(--space-sm, 8px) var(--space-md, 12px);
281
+ border: 1px solid var(--border, #E2E8F0);
282
+ border-radius: var(--radius-sm, 4px);
283
+ display: flex;
284
+ align-items: center;
285
+ gap: var(--space-md, 12px);
286
+ font-size: 0.75rem;
287
+ background: var(--bg-card, white);
288
+ }
289
+
290
+ .stratum-cascade-diff__label {
291
+ color: var(--text-tertiary, #64748B);
292
+ font-weight: 500;
293
+ }
294
+
295
+ .stratum-cascade-diff__stat {
296
+ padding: 2px 8px;
297
+ border-radius: 9999px;
298
+ font-weight: 600;
299
+ font-size: 0.6875rem;
300
+ cursor: default;
301
+ }
302
+
303
+ .stratum-cascade-diff__stat--inherited {
304
+ color: var(--color-accent, #0D9488);
305
+ background: var(--color-accent-light, #CCFBF1);
306
+ }
307
+
308
+ .stratum-cascade-diff__stat--locked {
309
+ color: var(--color-warning, #D97706);
310
+ background: var(--color-warning-bg, #FEF3C7);
311
+ }
312
+
313
+ .stratum-cascade-diff__stat--own {
314
+ color: var(--text-secondary, #475569);
315
+ background: var(--bg-input, var(--color-100, #F1F5F9));
316
+ }
317
+
318
+ [data-theme="dark"] .stratum-cascade-diff__stat--inherited {
319
+ background: rgba(13, 148, 136, 0.15);
320
+ }
321
+
322
+ [data-theme="dark"] .stratum-cascade-diff__stat--locked {
323
+ background: rgba(217, 119, 6, 0.15);
324
+ }
325
+
326
+ /* Responsive: stack on narrow screens */
327
+ @media (max-width: 768px) {
328
+ .stratum-cascade-split {
329
+ flex-direction: column;
330
+ }
331
+
332
+ .stratum-cascade-arrow {
333
+ flex-direction: row;
334
+ padding: 0 var(--space-xl, 24px);
335
+ }
336
+
337
+ .stratum-cascade-arrow__line {
338
+ width: 24px;
339
+ height: 2px;
340
+ }
341
+
342
+ .stratum-cascade-arrow__head {
343
+ transform: rotate(90deg);
344
+ }
345
+ }
346
+
347
+ @media (prefers-reduced-motion: reduce) {
348
+ .stratum-cascade-row--highlight {
349
+ transition: none;
350
+ }
351
+ }
352
+ `;
353
+ //# sourceMappingURL=ConfigInheritanceVisualizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigInheritanceVisualizer.js","sourceRoot":"","sources":["../../src/components/ConfigInheritanceVisualizer.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;AAEH,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMnD,SAAS,KAAK,CAAC,EAAE,IAAI,EAA4C;IAC/D,MAAM,MAAM,GAAuE;QACjF,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,kCAAkC,EAAE;QAChG,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,+BAA+B,EAAE;QACvF,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,4BAA4B,EAAE;KAC/E,CAAC;IACF,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CACL,gBAAM,SAAS,EAAE,yBAAyB,CAAC,CAAC,SAAS,EAAE,aACpD,CAAC,CAAC,IAAI,OAAG,CAAC,CAAC,KAAK,IACZ,CACR,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,KAAK,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAClC,IAAI,KAAK,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,EACnB,OAAO,EACP,KAAK,EACL,QAAQ,EACR,YAAY,GAMb;IACC,OAAO,CACL,eAAK,SAAS,EAAC,uBAAuB,aACpC,eAAK,SAAS,EAAC,+BAA+B,aAC5C,eAAM,SAAS,EAAC,8BAA8B,YAAE,KAAK,GAAQ,EAC5D,QAAQ,IAAI,eAAM,SAAS,EAAC,iCAAiC,YAAE,QAAQ,GAAQ,IAC5E,EACN,iBAAO,SAAS,EAAC,uBAAuB,aACtC,0BACE,yBACE,+BAAY,EACZ,iCAAc,EACd,kCAAe,IACZ,GACC,EACR,4BACG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACtB,cAEE,SAAS,EAAE,YAAY,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,EAAE,aAE7E,aAAI,SAAS,EAAC,qBAAqB,YAAE,KAAK,CAAC,GAAG,GAAM,EACpD,aAAI,SAAS,EAAC,uBAAuB,YACnC,yBAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAQ,GACvC,EACL,uBACE,KAAC,KAAK,IAAC,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,GAAI,GACjC,KATA,KAAK,CAAC,GAAG,CAUX,CACN,CAAC,EACD,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CACvB,uBACE,aAAI,OAAO,EAAE,CAAC,EAAE,SAAS,EAAC,uBAAuB,iCAE5C,GACF,CACN,IACK,IACF,IACJ,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,EAAE,SAAS,EAAoC;IACzF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC7D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAC;IAC9D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEtE,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,cAAK,SAAS,EAAE,mBAAmB,SAAS,IAAI,EAAE,EAAE,YAClD,KAAC,aAAa,IAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,GAAI,GAClC,CACP,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,eAAK,SAAS,EAAE,0CAA0C,SAAS,IAAI,EAAE,EAAE,aACzE,6DAAqC,KAAK,CAAC,OAAO,IAAK,EACvD,iBAAQ,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAC,uBAAuB,sBAEhE,IACL,CACP,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,WAAW,GAA6B,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAE3E,OAAO,CACL,eAAK,SAAS,EAAE,mBAAmB,SAAS,IAAI,EAAE,EAAE,aAClD,0BAAQ,aAAa,GAAS,EAG7B,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAC3B,cAAK,SAAS,EAAC,sBAAsB,EAAC,IAAI,EAAC,SAAS,YACjD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAC/B,iBAEE,IAAI,EAAC,KAAK,mBACK,CAAC,KAAK,aAAa,EAClC,SAAS,EAAE,sBAAsB,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EACvE,OAAO,EAAE,GAAG,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAE7D,KAAK,CAAC,IAAI,IANN,KAAK,CAAC,EAAE,CAON,CACV,CAAC,GACE,CACP,EAGD,eAAK,SAAS,EAAC,uBAAuB,aACpC,KAAC,WAAW,IACV,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,EAC3B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EACvB,QAAQ,EAAC,QAAQ,EACjB,YAAY,EAAE,YAAY,GAC1B,EAGF,eAAK,SAAS,EAAC,uBAAuB,iBAAa,MAAM,aACvD,cAAK,SAAS,EAAC,6BAA6B,GAAG,EAC/C,cAAK,SAAS,EAAC,6BAA6B,YAAE,QAAQ,GAAO,IACzD,EAEL,WAAW,CAAC,CAAC,CAAC,CACb,KAAC,WAAW,IACV,OAAO,EAAE,WAAW,CAAC,MAAM,EAC3B,KAAK,EAAE,WAAW,CAAC,IAAI,EACvB,QAAQ,EAAC,OAAO,EAChB,YAAY,EAAE,YAAY,GAC1B,CACH,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,oDAAoD,aACjE,cAAK,SAAS,EAAC,+BAA+B,YAC5C,eAAM,SAAS,EAAC,8BAA8B,4BAAmB,GAC7D,EACN,YAAG,SAAS,EAAC,+BAA+B,6GAGxC,IACA,CACP,IACG,EAGL,WAAW,IAAI,CACd,eAAK,SAAS,EAAC,sBAAsB,aACnC,eAAM,SAAS,EAAC,6BAA6B,qCAA4B,EACxE,CAAC,GAAG,EAAE;wBACL,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;wBACpF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;wBACjE,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;wBAC/E,OAAO,CACL,8BACG,SAAS,GAAG,CAAC,IAAI,CAChB,gBACE,SAAS,EAAC,kEAAkE,EAC5E,YAAY,EAAE,GAAG,EAAE;wCACjB,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAC5C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAChC,CAAC;wCACF,IAAI,cAAc;4CAAE,eAAe,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;oCAC1D,CAAC,EACD,YAAY,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,aAExC,SAAS,kBACL,CACR,EACA,MAAM,GAAG,CAAC,IAAI,CACb,gBAAM,SAAS,EAAC,+DAA+D,aAC5E,MAAM,eACF,CACR,EACA,GAAG,GAAG,CAAC,IAAI,CACV,gBAAM,SAAS,EAAC,4DAA4D,aACzE,GAAG,mBACC,CACR,IACA,CACJ,CAAC;oBACJ,CAAC,CAAC,EAAE,IACA,CACP,IACG,CACP,CAAC;AACJ,CAAC;AAED,iEAAiE;AAEjE,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmSrB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * DraggableTenantTree — TenantTree with drag-and-drop support.
3
+ *
4
+ * Supports two operations:
5
+ * - **Reparenting**: drag a tenant onto a different parent → calls moveTenant API
6
+ * - **Sibling reordering**: drag a tenant above/below a sibling → calls reorderTenant API
7
+ *
8
+ * Uses a dedicated drag handle (⠿) so clicking the node still selects it
9
+ * and clicking the expand/collapse arrow still works.
10
+ *
11
+ * ┌──────────────────────────────────┐
12
+ * │ ⠿ AcmeSec │
13
+ * │ ⠿ ├── NorthStar MSP │
14
+ * │ ⠿ │ ├── Client Alpha ← drag │
15
+ * │ ⠿ │ └── Client Beta │
16
+ * │ ⠿ └── SouthShield MSP ← drop │
17
+ * │ ⠿ └── Client Gamma │
18
+ * └──────────────────────────────────┘
19
+ */
20
+ export interface DraggableTenantTreeProps {
21
+ rootId?: string;
22
+ onSelect?: (tenantId: string) => void;
23
+ onMove?: (tenantId: string, newParentId: string) => void;
24
+ onReorder?: (tenantId: string, position: number) => void;
25
+ onEdit?: (tenantId: string, currentName: string) => void;
26
+ onArchive?: (tenantId: string, name: string) => void;
27
+ onAddChild?: (parentId: string) => void;
28
+ className?: string;
29
+ }
30
+ export declare function DraggableTenantTree({ rootId, onSelect, onMove, onReorder, onEdit, onArchive, onAddChild, className, }: DraggableTenantTreeProps): import("react/jsx-runtime").JSX.Element;
31
+ //# sourceMappingURL=DraggableTenantTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DraggableTenantTree.d.ts","sourceRoot":"","sources":["../../src/components/DraggableTenantTree.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkBH,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsJD,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,QAAQ,EACR,MAAM,EACN,SAAS,EACT,MAAM,EACN,SAAS,EACT,UAAU,EACV,SAAS,GACV,EAAE,wBAAwB,2CAyI1B"}