@burdenoff/fluidgrids-fe-sdk 2026.1104.3 → 2026.1105.2

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 (69) hide show
  1. package/README.md +38 -0
  2. package/dist/ExecutionDetailPage-HQB2SWBP.js +28 -0
  3. package/dist/ExecutionsListPage-RSLL634L.js +22 -0
  4. package/dist/WorkflowBuilder-E3PNZX74.js +32 -0
  5. package/dist/WorkflowsList-473FRRP2.js +21 -0
  6. package/dist/{agentTools-SZZN6TP3.js → agentTools-5N3ZEZDW.js} +8 -7
  7. package/dist/{chunk-NIY6R42C.js → chunk-2KUZBEWW.js} +7 -5
  8. package/dist/{chunk-NTWG3CJX.js → chunk-3IXU7WUC.js} +32 -21
  9. package/dist/{chunk-AAIZ6S6E.js → chunk-3QCRKKTI.js} +70 -88
  10. package/dist/{chunk-WTV6SQYK.js → chunk-3XUWPDKJ.js} +616 -25
  11. package/dist/{chunk-XCSCD3IU.js → chunk-5CFCFA6O.js} +8 -7
  12. package/dist/{chunk-DFIX6YWP.js → chunk-62CCBMDC.js} +40 -21
  13. package/dist/{chunk-KHXRYQYP.js → chunk-64JN2TVX.js} +4 -3
  14. package/dist/{chunk-NYBL5WHP.js → chunk-6IS7EXIY.js} +3 -3
  15. package/dist/{chunk-YYVRBROH.js → chunk-6ZK4MRVA.js} +1 -1
  16. package/dist/{chunk-4YCMMBSK.js → chunk-AJVU5YW6.js} +3 -3
  17. package/dist/{chunk-NGXJHYV5.js → chunk-AMXJLVZN.js} +2 -2
  18. package/dist/{chunk-PXIFUMLA.js → chunk-AU7LACOY.js} +16 -11
  19. package/dist/{chunk-GEY7RXRZ.js → chunk-CH3YUGWR.js} +4 -4
  20. package/dist/{chunk-XNU2PLJ2.js → chunk-CNKTQ5MG.js} +189 -9
  21. package/dist/{chunk-BIB7IH26.js → chunk-EYQ7GJRW.js} +5 -5
  22. package/dist/{chunk-X6PIU7FE.js → chunk-GKFMK7FF.js} +4 -3
  23. package/dist/{chunk-NJRCAE6K.js → chunk-HK76ZUAK.js} +5 -5
  24. package/dist/{chunk-F7LQL43U.js → chunk-IL343FKX.js} +2 -2
  25. package/dist/{chunk-5D4XS3WJ.js → chunk-J3YQCEP3.js} +18 -4
  26. package/dist/{chunk-4EUEKSEQ.js → chunk-L2N6DDOI.js} +2 -2
  27. package/dist/chunk-NZAYYUQ4.js +172 -0
  28. package/dist/{chunk-ON7LK6QH.js → chunk-O7CJJNW6.js} +278 -197
  29. package/dist/{chunk-ZDCJPQ5M.js → chunk-OXXXUAWM.js} +2 -2
  30. package/dist/{chunk-D4WA2M2N.js → chunk-QFC6E3WD.js} +4 -3
  31. package/dist/{chunk-AFX3EKFN.js → chunk-QFGZXWTM.js} +16 -4
  32. package/dist/{chunk-IK7IGG6T.js → chunk-QPLFALVV.js} +9 -8
  33. package/dist/{chunk-MF7JLSJX.js → chunk-SALZ3LQB.js} +11 -2
  34. package/dist/{chunk-SS7Y66P5.js → chunk-TCIBTMJI.js} +70 -4
  35. package/dist/{chunk-OMB3WMDQ.js → chunk-TNFBRXU7.js} +11 -10
  36. package/dist/chunk-UEG2WC3G.js +502 -0
  37. package/dist/chunk-US5QSLPV.js +316 -0
  38. package/dist/{chunk-5UHAB75U.js → chunk-W5WML3OO.js} +1 -1
  39. package/dist/chunk-WZ3EJVS6.js +93 -0
  40. package/dist/{chunk-Q72EOY4T.js → chunk-X25NCWG2.js} +9 -3
  41. package/dist/{chunk-VDJFTZ2H.js → chunk-XFH6SLDK.js} +4 -93
  42. package/dist/{chunk-TBHAZK52.js → chunk-Y6M7K4UG.js} +1 -1
  43. package/dist/{chunk-AVHBWJRY.js → chunk-Z3ABLERJ.js} +3 -1
  44. package/dist/client-YVZMLEQX.js +3 -0
  45. package/dist/config-66FUPSG5.js +1 -0
  46. package/dist/executions.js +18 -15
  47. package/dist/global-client-N5EIFW6T.js +3 -0
  48. package/dist/history.js +9 -8
  49. package/dist/index.d.ts +172 -133
  50. package/dist/index.js +95 -74
  51. package/dist/{node-detail-view-GAGSLHAO.js → node-detail-view-WIWW5N6N.js} +36 -11
  52. package/dist/nodes.js +5 -3
  53. package/dist/observability.js +10 -8
  54. package/dist/{quick-config-panel-44RBX6YR.js → quick-config-panel-O64TXXK3.js} +10 -8
  55. package/dist/settings.js +11 -9
  56. package/dist/templates.js +15 -14
  57. package/dist/{workflow-builder-BMGVSwpy.d.ts → workflow-builder-7vv9dCdp.d.ts} +413 -2
  58. package/dist/workflow-builder.d.ts +2 -1
  59. package/dist/workflow-builder.js +17 -16
  60. package/dist/workflows-list.js +11 -10
  61. package/package.json +1 -1
  62. package/dist/ExecutionDetailPage-ND2VMU45.js +0 -25
  63. package/dist/ExecutionsListPage-EZ65FXER.js +0 -20
  64. package/dist/WorkflowBuilder-4I44FWII.js +0 -31
  65. package/dist/WorkflowsList-YFD2RKKQ.js +0 -20
  66. package/dist/chunk-6AMNEX2Y.js +0 -214
  67. package/dist/client-EYQDMR4O.js +0 -1
  68. package/dist/config-3DBXLCK3.js +0 -1
  69. package/dist/global-client-O2HCG5CJ.js +0 -1
@@ -1,7 +1,7 @@
1
- import { throwIfResultError } from './chunk-AAIZ6S6E.js';
2
- import { RunFailureClustersDocument, DismissRunFailureClusterDocument, RunFailureTriageSettingsDocument, SetRunFailureTriageEnabledDocument, FgTriageFailedRunsDocument } from './chunk-AVHBWJRY.js';
1
+ import { RunFailureClustersDocument, DismissRunFailureClusterDocument, RunFailureTriageSettingsDocument, SetRunFailureTriageEnabledDocument, FgTriageFailedRunsDocument } from './chunk-Z3ABLERJ.js';
3
2
  import { useTr } from './chunk-UULVIT25.js';
4
- import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
3
+ import { getFluidGridsClient } from './chunk-3IXU7WUC.js';
4
+ import { throwIfResultError } from './chunk-US5QSLPV.js';
5
5
  import { useState, useCallback, useEffect } from 'react';
6
6
  import { Icon } from '@iconify/react';
7
7
  import { Button } from '@burdenoff/fe-libs/ui';
@@ -325,4 +325,70 @@ function FailureTriagePanel({
325
325
  );
326
326
  }
327
327
 
328
- export { BUCKET_LABELS, FailureTriagePanel, OPEN_STATUSES, dismissRunFailureCluster, fetchRunFailureClusters };
328
+ // src/modules/observability/utils.ts
329
+ function percentage(value, total) {
330
+ if (total <= 0) return 0;
331
+ return Math.round(value / total * 1e3) / 10;
332
+ }
333
+ function getFailureBreakdown(runs) {
334
+ const counts = /* @__PURE__ */ new Map();
335
+ for (const run of runs) {
336
+ const key = run.errorType || "UNKNOWN";
337
+ counts.set(key, (counts.get(key) ?? 0) + 1);
338
+ }
339
+ return [...counts.entries()].map(([key, count]) => ({ key, count })).sort((a, b) => b.count - a.count || a.key.localeCompare(b.key));
340
+ }
341
+ function getTopFailingWorkflows(runs) {
342
+ const counts = /* @__PURE__ */ new Map();
343
+ for (const run of runs) {
344
+ const current = counts.get(run.workflowKey);
345
+ if (current) {
346
+ current.count += 1;
347
+ } else {
348
+ counts.set(run.workflowKey, {
349
+ workflowKey: run.workflowKey,
350
+ label: run.workflow?.name || run.workflowKey,
351
+ count: 1
352
+ });
353
+ }
354
+ }
355
+ return [...counts.values()].sort(
356
+ (a, b) => b.count - a.count || a.label.localeCompare(b.label)
357
+ );
358
+ }
359
+ function getTopFailingNodes(nodeUsageStats) {
360
+ return [...nodeUsageStats].filter((stat) => stat.failureCount > 0).sort(
361
+ (a, b) => b.failureCount - a.failureCount || a.nodeType.localeCompare(b.nodeType)
362
+ );
363
+ }
364
+ function formatDuration(seconds) {
365
+ if (seconds === null || seconds === void 0 || !Number.isFinite(seconds)) {
366
+ return "\u2014";
367
+ }
368
+ if (seconds < 1) return `${Math.round(seconds * 1e3)}ms`;
369
+ if (seconds < 60) return `${seconds.toFixed(1)}s`;
370
+ const minutes = Math.floor(seconds / 60);
371
+ const remainingSeconds = Math.round(seconds % 60);
372
+ return `${minutes}m ${remainingSeconds}s`;
373
+ }
374
+ function formatBytes(bytes) {
375
+ if (!Number.isFinite(bytes) || bytes < 0) return "\u2014";
376
+ if (bytes < 1024) return `${bytes} B`;
377
+ const units = ["KB", "MB", "GB", "TB"];
378
+ let value = bytes / 1024;
379
+ let unit = units[0];
380
+ for (let i = 1; i < units.length && value >= 1024; i += 1) {
381
+ value /= 1024;
382
+ unit = units[i];
383
+ }
384
+ return `${value.toFixed(value >= 10 ? 0 : 1)} ${unit}`;
385
+ }
386
+ function prettyJson(value) {
387
+ try {
388
+ return JSON.stringify(value, null, 2) ?? "null";
389
+ } catch {
390
+ return String(value);
391
+ }
392
+ }
393
+
394
+ export { BUCKET_LABELS, FailureTriagePanel, OPEN_STATUSES, dismissRunFailureCluster, fetchRunFailureClusters, formatBytes, formatDuration, getFailureBreakdown, getTopFailingNodes, getTopFailingWorkflows, percentage, prettyJson };
@@ -1,13 +1,14 @@
1
- import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-TBHAZK52.js';
1
+ import { isGuidedTourIntent, pickGuidedTour, withoutGuidedTourIntent, isCreateIntent, CreateWorkflowRefusalDialog, decideMissingWorkflow } from './chunk-Y6M7K4UG.js';
2
2
  import { registerLiveCanvasHandler } from './chunk-PIKYQE7P.js';
3
- import { useWorkflowReloadStore, releaseLeaseKeptForReload, useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-DFIX6YWP.js';
4
- import { canvasFromDefinition } from './chunk-KHXRYQYP.js';
5
- import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-AFX3EKFN.js';
6
- import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, rememberRevision, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes, throwIfResultError } from './chunk-AAIZ6S6E.js';
7
- import { getFluidGridsConfig } from './chunk-6AMNEX2Y.js';
8
- import { WorkflowDefinitionDocument } from './chunk-AVHBWJRY.js';
3
+ import { useWorkflowReloadStore, releaseLeaseKeptForReload, useInstalledNodes, buildNodeCheck, FlowBuilderPage, buildRequiredNodeTypes } from './chunk-62CCBMDC.js';
4
+ import { canvasFromDefinition } from './chunk-64JN2TVX.js';
5
+ import { useLazyWorkflowDefinition, useCreateWorkflow } from './chunk-QFGZXWTM.js';
6
+ import { useFlowStore, refetchStoreNodes, BILLING_PLANS_PATH, codeBuildIdOf, mergeStickyNotes, rememberRevision, blankWorkflowCreateInput, classifyCreateRefusal, useSaveStatusStore, workflowFingerprint, registerWorkflowNodeTypes } from './chunk-3QCRKKTI.js';
7
+ import { WorkflowDefinitionDocument } from './chunk-Z3ABLERJ.js';
9
8
  import { useTr } from './chunk-UULVIT25.js';
10
- import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
9
+ import { getFluidGridsClient } from './chunk-3IXU7WUC.js';
10
+ import { throwIfResultError } from './chunk-US5QSLPV.js';
11
+ import { getFluidGridsConfig } from './chunk-UEG2WC3G.js';
11
12
  import { useLocation, useNavigate, useParams } from 'react-router';
12
13
  import { toast } from 'sonner';
13
14
  import { Icon } from '@iconify/react';
@@ -792,9 +793,9 @@ function WorkflowItem({
792
793
  setInstalling(true);
793
794
  setInstallErrors([]);
794
795
  try {
795
- const { getGlobalStoreClient } = await import('./global-client-O2HCG5CJ.js');
796
+ const { getGlobalStoreClient } = await import('./global-client-N5EIFW6T.js');
796
797
  const { InstallWorkflowNodeDocument } = await import('./global-operations-BZDHTSYP.js');
797
- const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-3DBXLCK3.js');
798
+ const { getFluidGridsConfig: getFluidGridsConfig2 } = await import('./config-66FUPSG5.js');
798
799
  const storeClient = getGlobalStoreClient();
799
800
  const cfg = getFluidGridsConfig2();
800
801
  for (let i = 0; i < nodesToInstall.length; i++) {
@@ -0,0 +1,502 @@
1
+ import { create } from 'zustand';
2
+
3
+ var defaultFilter = {
4
+ status: "all",
5
+ workflowKey: "",
6
+ dateRange: {
7
+ start: null,
8
+ end: null,
9
+ preset: "all"
10
+ },
11
+ search: "",
12
+ triggerType: "all",
13
+ durationMinSeconds: null,
14
+ durationMaxSeconds: null,
15
+ errorType: "all",
16
+ nodeId: "",
17
+ tagId: "",
18
+ workflowId: ""
19
+ };
20
+ var defaultPagination = {
21
+ page: 1,
22
+ pageSize: 25,
23
+ total: 0
24
+ };
25
+ var useExecutionsStore = create((set) => ({
26
+ // Initial state
27
+ viewMode: "table",
28
+ selectedExecution: null,
29
+ expandedRows: /* @__PURE__ */ new Set(),
30
+ selection: {
31
+ runIds: [],
32
+ allSelected: false
33
+ },
34
+ filter: defaultFilter,
35
+ pagination: defaultPagination,
36
+ isFilterPanelOpen: false,
37
+ isDetailsPanelOpen: false,
38
+ autoRefresh: true,
39
+ autoRefreshInterval: 5e3,
40
+ liveRunIds: /* @__PURE__ */ new Set(),
41
+ // Actions - View
42
+ setViewMode: (mode) => set({ viewMode: mode }),
43
+ setSelectedExecution: (execution) => set({
44
+ selectedExecution: execution,
45
+ isDetailsPanelOpen: execution !== null
46
+ }),
47
+ toggleRowExpanded: (runId) => set((state) => {
48
+ const newExpanded = new Set(state.expandedRows);
49
+ if (newExpanded.has(runId)) {
50
+ newExpanded.delete(runId);
51
+ } else {
52
+ newExpanded.add(runId);
53
+ }
54
+ return { expandedRows: newExpanded };
55
+ }),
56
+ // Actions - Selection
57
+ setSelection: (selection) => set({ selection }),
58
+ toggleSelectRun: (runId) => set((state) => {
59
+ const isSelected = state.selection.runIds.includes(runId);
60
+ const newRunIds = isSelected ? state.selection.runIds.filter((id) => id !== runId) : [...state.selection.runIds, runId];
61
+ return {
62
+ selection: {
63
+ runIds: newRunIds,
64
+ allSelected: false
65
+ }
66
+ };
67
+ }),
68
+ selectAll: (runIds) => set((state) => ({
69
+ selection: {
70
+ runIds: state.selection.allSelected ? [] : runIds,
71
+ allSelected: !state.selection.allSelected
72
+ }
73
+ })),
74
+ clearSelection: () => set({
75
+ selection: {
76
+ runIds: [],
77
+ allSelected: false
78
+ }
79
+ }),
80
+ // Actions - Filter
81
+ updateFilter: (filterUpdate) => set((state) => ({
82
+ filter: { ...state.filter, ...filterUpdate },
83
+ pagination: { ...state.pagination, page: 1 }
84
+ })),
85
+ setStatusFilter: (status) => set((state) => ({
86
+ filter: { ...state.filter, status },
87
+ pagination: { ...state.pagination, page: 1 }
88
+ })),
89
+ setWorkflowFilter: (workflowKey) => set((state) => ({
90
+ filter: { ...state.filter, workflowKey },
91
+ pagination: { ...state.pagination, page: 1 }
92
+ })),
93
+ setDateRange: (dateRange) => set((state) => ({
94
+ filter: { ...state.filter, dateRange },
95
+ pagination: { ...state.pagination, page: 1 }
96
+ })),
97
+ setSearchQuery: (search) => set((state) => ({
98
+ filter: { ...state.filter, search },
99
+ pagination: { ...state.pagination, page: 1 }
100
+ })),
101
+ setTriggerTypeFilter: (triggerType) => set((state) => ({
102
+ filter: { ...state.filter, triggerType },
103
+ pagination: { ...state.pagination, page: 1 }
104
+ })),
105
+ setDurationFilter: (durationMinSeconds, durationMaxSeconds) => set((state) => ({
106
+ filter: { ...state.filter, durationMinSeconds, durationMaxSeconds },
107
+ pagination: { ...state.pagination, page: 1 }
108
+ })),
109
+ setErrorTypeFilter: (errorType) => set((state) => ({
110
+ filter: { ...state.filter, errorType },
111
+ pagination: { ...state.pagination, page: 1 }
112
+ })),
113
+ setNodeFilter: (nodeId) => set((state) => ({
114
+ filter: { ...state.filter, nodeId },
115
+ pagination: { ...state.pagination, page: 1 }
116
+ })),
117
+ setTagFilter: (tagId) => set((state) => ({
118
+ filter: { ...state.filter, tagId },
119
+ pagination: { ...state.pagination, page: 1 }
120
+ })),
121
+ setWorkflowIdFilter: (workflowId) => set((state) => ({
122
+ filter: { ...state.filter, workflowId },
123
+ pagination: { ...state.pagination, page: 1 }
124
+ })),
125
+ resetFilters: () => set({
126
+ filter: defaultFilter,
127
+ pagination: { ...defaultPagination }
128
+ }),
129
+ // Actions - Pagination
130
+ setPage: (page) => set((state) => ({
131
+ pagination: { ...state.pagination, page }
132
+ })),
133
+ setPageSize: (pageSize) => set((state) => ({
134
+ pagination: { ...state.pagination, pageSize, page: 1 }
135
+ })),
136
+ setTotal: (total) => set((state) => ({
137
+ pagination: { ...state.pagination, total }
138
+ })),
139
+ // Actions - UI
140
+ toggleFilterPanel: () => set((state) => ({
141
+ isFilterPanelOpen: !state.isFilterPanelOpen
142
+ })),
143
+ toggleDetailsPanel: () => set((state) => ({
144
+ isDetailsPanelOpen: !state.isDetailsPanelOpen
145
+ })),
146
+ setAutoRefresh: (enabled) => set({ autoRefresh: enabled }),
147
+ setAutoRefreshInterval: (interval) => set({ autoRefreshInterval: interval }),
148
+ // Actions - Real-time
149
+ addLiveRun: (runId) => set((state) => {
150
+ const newLiveRunIds = new Set(state.liveRunIds);
151
+ newLiveRunIds.add(runId);
152
+ return { liveRunIds: newLiveRunIds };
153
+ }),
154
+ removeLiveRun: (runId) => set((state) => {
155
+ const newLiveRunIds = new Set(state.liveRunIds);
156
+ newLiveRunIds.delete(runId);
157
+ return { liveRunIds: newLiveRunIds };
158
+ }),
159
+ clearLiveRuns: () => set({ liveRunIds: /* @__PURE__ */ new Set() })
160
+ }));
161
+
162
+ // src/theme/fluidgridsTheme.ts
163
+ var color = (...cssVariables) => ({
164
+ kind: "color",
165
+ cssVariables
166
+ });
167
+ var length = (...cssVariables) => ({
168
+ kind: "length",
169
+ cssVariables
170
+ });
171
+ var font = (...cssVariables) => ({
172
+ kind: "font",
173
+ cssVariables
174
+ });
175
+ var FLUIDGRIDS_THEME_TOKEN_MAP = {
176
+ "colors.bgCanvas": color("--color-bg-canvas"),
177
+ "colors.bgSurface": color("--color-bg-surface"),
178
+ "colors.bgElevated": color("--color-bg-elevated"),
179
+ "colors.bgSunken": color("--color-bg-sunken"),
180
+ "colors.textPrimary": color("--color-text-primary"),
181
+ "colors.textSecondary": color("--color-text-secondary"),
182
+ "colors.textMuted": color("--color-text-muted"),
183
+ "colors.borderDefault": color("--color-border-default"),
184
+ "colors.borderSubtle": color("--color-border-subtle"),
185
+ "colors.borderStrong": color("--color-border-strong"),
186
+ "colors.primary": color(
187
+ "--color-action-primary-bg",
188
+ "--color-action-primary-border"
189
+ ),
190
+ "colors.primaryHover": color("--color-action-primary-bgHover"),
191
+ "colors.primaryActive": color("--color-action-primary-bgActive"),
192
+ "colors.primaryText": color("--color-action-primary-text"),
193
+ "colors.success": color("--color-status-success-bg"),
194
+ "colors.warning": color("--color-status-warning-bg"),
195
+ "colors.error": color("--color-status-error-bg"),
196
+ "colors.info": color("--color-status-info-bg"),
197
+ "radius.base": length("--radius"),
198
+ "radius.card": length("--radius-card"),
199
+ "radius.button": length("--radius-button"),
200
+ "radius.input": length("--radius-input"),
201
+ "font.body": font("--font-family-body", "--font-sans"),
202
+ "font.heading": font("--font-family-heading"),
203
+ "font.mono": font("--font-family-mono", "--font-mono")
204
+ };
205
+ var MAX_VALUE_LENGTH = 200;
206
+ var FORBIDDEN_VALUE = /[;{}<>\\!@"`]|\/\*|\*\/|url\s*\(|expression\s*\(|image\s*\(|image-set\s*\(|javascript:|@import/i;
207
+ var HEX_COLOR = /^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
208
+ var NAMED_COLOR = /^[a-z]{3,30}$/i;
209
+ var COLOR_FUNCTION = /^(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|color-mix)\([a-z0-9#%.,/\s()+-]*\)$/i;
210
+ var CSS_VAR = /^var\(--[a-z0-9-]+\)$/i;
211
+ var LENGTH = /^(?:0|\d*\.?\d+(?:px|rem|em|%|vh|vw|vmin|vmax|ch|ex|pt))$/i;
212
+ var CALC = /^calc\([a-z0-9%.\s()*/+-]*\)$/i;
213
+ var FONT_FAMILY_ITEM = /^(?:[a-z0-9][a-z0-9 _-]*|'[a-z0-9 _-]+')$/i;
214
+ function balancedParentheses(value) {
215
+ let depth = 0;
216
+ for (const char of value) {
217
+ if (char === "(") depth += 1;
218
+ if (char === ")") depth -= 1;
219
+ if (depth < 0) return false;
220
+ }
221
+ return depth === 0;
222
+ }
223
+ function sanitizeThemeValue(kind, value) {
224
+ if (typeof value !== "string") return null;
225
+ const trimmed = value.trim();
226
+ if (!trimmed || trimmed.length > MAX_VALUE_LENGTH) return null;
227
+ if (FORBIDDEN_VALUE.test(trimmed) || !balancedParentheses(trimmed)) {
228
+ return null;
229
+ }
230
+ if (CSS_VAR.test(trimmed)) return trimmed;
231
+ switch (kind) {
232
+ case "color":
233
+ return HEX_COLOR.test(trimmed) || NAMED_COLOR.test(trimmed) || COLOR_FUNCTION.test(trimmed) ? trimmed : null;
234
+ case "length":
235
+ return LENGTH.test(trimmed) || CALC.test(trimmed) ? trimmed : null;
236
+ case "font": {
237
+ const items = trimmed.split(",").map((item) => item.trim());
238
+ return items.every((item) => FONT_FAMILY_ITEM.test(item)) ? items.join(", ") : null;
239
+ }
240
+ }
241
+ }
242
+ function warnDropped(key, value) {
243
+ console.warn(
244
+ `[FluidGrids SDK] theme token "${key}" ignored: ${JSON.stringify(value)} is not a plain CSS value.`
245
+ );
246
+ }
247
+ function hexLuminance(value) {
248
+ if (!HEX_COLOR.test(value)) return null;
249
+ let hex = value.slice(1);
250
+ if (hex.length <= 4) {
251
+ hex = hex.split("").map((digit) => digit + digit).join("");
252
+ }
253
+ const channels = [0, 2, 4].map((offset) => {
254
+ const channel = parseInt(hex.slice(offset, offset + 2), 16) / 255;
255
+ return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
256
+ });
257
+ const [red = 0, green = 0, blue = 0] = channels;
258
+ return 0.2126 * red + 0.7152 * green + 0.0722 * blue;
259
+ }
260
+ function themeMode(theme) {
261
+ if (theme === "light" || theme === "dark") return theme;
262
+ if (theme && typeof theme === "object") {
263
+ return theme.mode === "light" || theme.mode === "dark" ? theme.mode : void 0;
264
+ }
265
+ return void 0;
266
+ }
267
+ function groupEntries(theme, group) {
268
+ const values = theme[group];
269
+ if (!values || typeof values !== "object") return [];
270
+ return Object.entries(values);
271
+ }
272
+ function isTokenKey(key) {
273
+ return Object.prototype.hasOwnProperty.call(FLUIDGRIDS_THEME_TOKEN_MAP, key);
274
+ }
275
+ function themeToCssVariables(theme) {
276
+ const variables = {};
277
+ if (!theme || typeof theme !== "object") return variables;
278
+ const colors = {};
279
+ for (const group of ["colors", "radius", "font"]) {
280
+ for (const [name, raw] of groupEntries(theme, group)) {
281
+ if (raw === void 0) continue;
282
+ const key = `${group}.${name}`;
283
+ if (!isTokenKey(key)) {
284
+ warnDropped(key, raw);
285
+ continue;
286
+ }
287
+ const mapping = FLUIDGRIDS_THEME_TOKEN_MAP[key];
288
+ const value = sanitizeThemeValue(mapping.kind, raw);
289
+ if (value === null) {
290
+ warnDropped(key, raw);
291
+ continue;
292
+ }
293
+ if (group === "colors") colors[name] = value;
294
+ for (const cssVariable of mapping.cssVariables) {
295
+ variables[cssVariable] = value;
296
+ }
297
+ }
298
+ }
299
+ const primary = colors.primary;
300
+ if (primary) {
301
+ if (!colors.primaryHover) {
302
+ variables["--color-action-primary-bgHover"] = `color-mix(in oklab, ${primary} 84%, var(--palette-black))`;
303
+ }
304
+ if (!colors.primaryActive) {
305
+ variables["--color-action-primary-bgActive"] = `color-mix(in oklab, ${primary} 70%, var(--palette-black))`;
306
+ }
307
+ if (!colors.primaryText) {
308
+ const luminance = hexLuminance(primary);
309
+ if (luminance !== null) {
310
+ variables["--color-action-primary-text"] = luminance > 0.4 ? "var(--palette-black)" : "var(--palette-white)";
311
+ }
312
+ }
313
+ }
314
+ return variables;
315
+ }
316
+ var stack = [];
317
+ var nextId = 1;
318
+ var observer = null;
319
+ var hostVariables = /* @__PURE__ */ new Map();
320
+ var appliedVariables = /* @__PURE__ */ new Map();
321
+ var hostMode = null;
322
+ function readHostMode(root) {
323
+ return {
324
+ dataTheme: root.getAttribute("data-theme"),
325
+ dark: root.classList.contains("dark")
326
+ };
327
+ }
328
+ function writeMode(root, mode) {
329
+ if (mode.dataTheme === null) root.removeAttribute("data-theme");
330
+ else if (root.getAttribute("data-theme") !== mode.dataTheme) {
331
+ root.setAttribute("data-theme", mode.dataTheme);
332
+ }
333
+ if (root.classList.contains("dark") !== mode.dark) {
334
+ root.classList.toggle("dark", mode.dark);
335
+ }
336
+ }
337
+ function modeDrifted(root, mode) {
338
+ return root.getAttribute("data-theme") !== mode || root.classList.contains("dark") !== (mode === "dark");
339
+ }
340
+ function restoreVariable(root, name) {
341
+ const previous = hostVariables.get(name) ?? "";
342
+ if (previous) root.style.setProperty(name, previous);
343
+ else root.style.removeProperty(name);
344
+ hostVariables.delete(name);
345
+ appliedVariables.delete(name);
346
+ }
347
+ function forceVariable(root, name, value) {
348
+ root.style.setProperty(name, value);
349
+ appliedVariables.set(name, root.style.getPropertyValue(name));
350
+ }
351
+ function reconcileDrift() {
352
+ const top = stack.at(-1);
353
+ if (!top || typeof document === "undefined") return;
354
+ const root = document.documentElement;
355
+ for (const [name, value] of Object.entries(top.variables)) {
356
+ const current = root.style.getPropertyValue(name);
357
+ if (current !== appliedVariables.get(name)) {
358
+ hostVariables.set(name, current);
359
+ forceVariable(root, name, value);
360
+ }
361
+ }
362
+ if (top.mode && modeDrifted(root, top.mode)) {
363
+ hostMode = readHostMode(root);
364
+ writeMode(root, { dataTheme: top.mode, dark: top.mode === "dark" });
365
+ }
366
+ }
367
+ function sync() {
368
+ if (typeof document === "undefined") return;
369
+ const root = document.documentElement;
370
+ const top = stack.at(-1);
371
+ const wanted = top?.variables ?? {};
372
+ for (const name of [...appliedVariables.keys()]) {
373
+ if (!(name in wanted)) restoreVariable(root, name);
374
+ }
375
+ for (const [name, value] of Object.entries(wanted)) {
376
+ if (!hostVariables.has(name)) {
377
+ hostVariables.set(name, root.style.getPropertyValue(name));
378
+ }
379
+ if (appliedVariables.get(name) !== value) forceVariable(root, name, value);
380
+ }
381
+ if (top?.mode) {
382
+ if (!hostMode) hostMode = readHostMode(root);
383
+ writeMode(root, { dataTheme: top.mode, dark: top.mode === "dark" });
384
+ } else if (hostMode) {
385
+ writeMode(root, hostMode);
386
+ hostMode = null;
387
+ }
388
+ if (!top) {
389
+ observer?.disconnect();
390
+ observer = null;
391
+ return;
392
+ }
393
+ if (!observer && typeof MutationObserver !== "undefined") {
394
+ observer = new MutationObserver(reconcileDrift);
395
+ observer.observe(root, {
396
+ attributes: true,
397
+ attributeFilter: ["style", "data-theme", "class"]
398
+ });
399
+ }
400
+ }
401
+ function applyFluidGridsTheme(theme) {
402
+ if (typeof document === "undefined") return () => void 0;
403
+ const entry = {
404
+ id: nextId++,
405
+ variables: themeToCssVariables(theme),
406
+ mode: themeMode(theme)
407
+ };
408
+ stack.push(entry);
409
+ sync();
410
+ let disposed = false;
411
+ return () => {
412
+ if (disposed) return;
413
+ disposed = true;
414
+ const index = stack.findIndex((active) => active.id === entry.id);
415
+ if (index >= 0) stack.splice(index, 1);
416
+ sync();
417
+ };
418
+ }
419
+ function themeKey(theme) {
420
+ if (!theme) return "";
421
+ if (typeof theme === "string") return theme;
422
+ const sortedGroup = (group) => groupEntries(theme, group).filter(([, value]) => value !== void 0).sort(([a], [b]) => a.localeCompare(b));
423
+ return JSON.stringify([
424
+ theme.mode ?? null,
425
+ sortedGroup("colors"),
426
+ sortedGroup("radius"),
427
+ sortedGroup("font")
428
+ ]);
429
+ }
430
+
431
+ // src/config/index.ts
432
+ var runtimeConfig = {
433
+ apiGatewayUrl: "",
434
+ workspaceId: ""
435
+ };
436
+ var config = new Proxy({}, {
437
+ get(_, prop) {
438
+ return runtimeConfig[prop];
439
+ }
440
+ });
441
+ function getFluidGridsConfig() {
442
+ return { ...runtimeConfig };
443
+ }
444
+ function setFluidGridsConfig(newConfig) {
445
+ const previous = runtimeConfig;
446
+ runtimeConfig = { ...runtimeConfig, ...newConfig };
447
+ if (previous.authToken !== runtimeConfig.authToken || previous.workspaceToken !== runtimeConfig.workspaceToken) {
448
+ tokenRevision += 1;
449
+ }
450
+ if ("theme" in newConfig) syncConfigTheme(newConfig.theme);
451
+ }
452
+ function resetFluidGridsConfig() {
453
+ tokenRevision += 1;
454
+ runtimeConfig = {
455
+ apiGatewayUrl: "",
456
+ workspaceId: ""
457
+ };
458
+ syncConfigTheme(void 0);
459
+ }
460
+ var tokenRevision = 0;
461
+ function getFluidGridsTokenRevision() {
462
+ return tokenRevision;
463
+ }
464
+ var configTheme = null;
465
+ function syncConfigTheme(theme) {
466
+ const key = themeKey(theme);
467
+ if (configTheme?.key === key) return;
468
+ const previous = configTheme;
469
+ configTheme = key ? { key, dispose: applyFluidGridsTheme(theme) } : null;
470
+ previous?.dispose();
471
+ }
472
+ function normalizeOrigin(origin) {
473
+ return origin.replace(/\/$/, "");
474
+ }
475
+ function validateTrustedOrigin(trustedOrigins) {
476
+ if (typeof window === "undefined" || !trustedOrigins?.length) {
477
+ return;
478
+ }
479
+ const currentOrigin = normalizeOrigin(window.location.origin);
480
+ const allowedOrigins = trustedOrigins.map(normalizeOrigin);
481
+ if (!allowedOrigins.includes(currentOrigin)) {
482
+ throw new Error(
483
+ `FluidGrids SDK blocked untrusted origin: ${currentOrigin}`
484
+ );
485
+ }
486
+ }
487
+ function getGraphQLEndpoint(baseUrl) {
488
+ const url = baseUrl || runtimeConfig.apiGatewayUrl;
489
+ if (!url) {
490
+ throw new Error("FluidGrids SDK requires apiGatewayUrl to be configured");
491
+ }
492
+ const normalizedBase = url.endsWith("/") ? url.slice(0, -1) : url;
493
+ if (normalizedBase.endsWith("/graphql")) {
494
+ return normalizedBase;
495
+ }
496
+ return `${normalizedBase}/workspaces/graphql`;
497
+ }
498
+ function resetFluidGridsExecutionState() {
499
+ useExecutionsStore.setState(useExecutionsStore.getInitialState(), true);
500
+ }
501
+
502
+ export { FLUIDGRIDS_THEME_TOKEN_MAP, applyFluidGridsTheme, config, getFluidGridsConfig, getFluidGridsTokenRevision, getGraphQLEndpoint, resetFluidGridsConfig, resetFluidGridsExecutionState, sanitizeThemeValue, setFluidGridsConfig, themeKey, themeToCssVariables, useExecutionsStore, validateTrustedOrigin };