@prismiq/react 0.1.0

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 (82) hide show
  1. package/README.md +88 -0
  2. package/dist/CustomSQLEditor-BXB4rf1q.d.cts +1297 -0
  3. package/dist/CustomSQLEditor-DYeId0Gp.d.ts +1297 -0
  4. package/dist/DashboardDialog-B3vYC5Gs.d.ts +1106 -0
  5. package/dist/DashboardDialog-LHmrtNQU.d.cts +1106 -0
  6. package/dist/accessibility-2yy5yqRR.d.cts +145 -0
  7. package/dist/accessibility-2yy5yqRR.d.ts +145 -0
  8. package/dist/charts/index.cjs +110 -0
  9. package/dist/charts/index.cjs.map +1 -0
  10. package/dist/charts/index.d.cts +2 -0
  11. package/dist/charts/index.d.ts +2 -0
  12. package/dist/charts/index.js +5 -0
  13. package/dist/charts/index.js.map +1 -0
  14. package/dist/chunk-2H5WTH4K.js +2409 -0
  15. package/dist/chunk-2H5WTH4K.js.map +1 -0
  16. package/dist/chunk-4AVL6GQK.cjs +470 -0
  17. package/dist/chunk-4AVL6GQK.cjs.map +1 -0
  18. package/dist/chunk-EX74SI67.js +455 -0
  19. package/dist/chunk-EX74SI67.js.map +1 -0
  20. package/dist/chunk-FEABEF3J.cjs +7543 -0
  21. package/dist/chunk-FEABEF3J.cjs.map +1 -0
  22. package/dist/chunk-JTCBZDHY.js +126 -0
  23. package/dist/chunk-JTCBZDHY.js.map +1 -0
  24. package/dist/chunk-LMTG3LRC.cjs +326 -0
  25. package/dist/chunk-LMTG3LRC.cjs.map +1 -0
  26. package/dist/chunk-MDXGGZSW.cjs +273 -0
  27. package/dist/chunk-MDXGGZSW.cjs.map +1 -0
  28. package/dist/chunk-MOAEEF5P.js +7510 -0
  29. package/dist/chunk-MOAEEF5P.js.map +1 -0
  30. package/dist/chunk-NK7HKX2J.cjs +2459 -0
  31. package/dist/chunk-NK7HKX2J.cjs.map +1 -0
  32. package/dist/chunk-NY6TZLST.cjs +8781 -0
  33. package/dist/chunk-NY6TZLST.cjs.map +1 -0
  34. package/dist/chunk-T6STUE7E.js +321 -0
  35. package/dist/chunk-T6STUE7E.js.map +1 -0
  36. package/dist/chunk-TRW7DKLP.cjs +141 -0
  37. package/dist/chunk-TRW7DKLP.cjs.map +1 -0
  38. package/dist/chunk-UPYINBZU.js +8706 -0
  39. package/dist/chunk-UPYINBZU.js.map +1 -0
  40. package/dist/chunk-WWTT2OJ5.js +246 -0
  41. package/dist/chunk-WWTT2OJ5.js.map +1 -0
  42. package/dist/components/index.cjs +222 -0
  43. package/dist/components/index.cjs.map +1 -0
  44. package/dist/components/index.d.cts +207 -0
  45. package/dist/components/index.d.ts +207 -0
  46. package/dist/components/index.js +5 -0
  47. package/dist/components/index.js.map +1 -0
  48. package/dist/dashboard/index.cjs +140 -0
  49. package/dist/dashboard/index.cjs.map +1 -0
  50. package/dist/dashboard/index.d.cts +302 -0
  51. package/dist/dashboard/index.d.ts +302 -0
  52. package/dist/dashboard/index.js +7 -0
  53. package/dist/dashboard/index.js.map +1 -0
  54. package/dist/export/index.cjs +32 -0
  55. package/dist/export/index.cjs.map +1 -0
  56. package/dist/export/index.d.cts +197 -0
  57. package/dist/export/index.d.ts +197 -0
  58. package/dist/export/index.js +3 -0
  59. package/dist/export/index.js.map +1 -0
  60. package/dist/index-C-Qcuu4Y.d.cts +821 -0
  61. package/dist/index-rPc7ijt8.d.ts +821 -0
  62. package/dist/index.cjs +1486 -0
  63. package/dist/index.cjs.map +1 -0
  64. package/dist/index.d.cts +1435 -0
  65. package/dist/index.d.ts +1435 -0
  66. package/dist/index.js +926 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/ssr/index.cjs +64 -0
  69. package/dist/ssr/index.cjs.map +1 -0
  70. package/dist/ssr/index.d.cts +213 -0
  71. package/dist/ssr/index.d.ts +213 -0
  72. package/dist/ssr/index.js +3 -0
  73. package/dist/ssr/index.js.map +1 -0
  74. package/dist/types-WrCbOeAV.d.cts +569 -0
  75. package/dist/types-WrCbOeAV.d.ts +569 -0
  76. package/dist/utils/index.cjs +64 -0
  77. package/dist/utils/index.cjs.map +1 -0
  78. package/dist/utils/index.d.cts +112 -0
  79. package/dist/utils/index.d.ts +112 -0
  80. package/dist/utils/index.js +3 -0
  81. package/dist/utils/index.js.map +1 -0
  82. package/package.json +110 -0
package/dist/index.js ADDED
@@ -0,0 +1,926 @@
1
+ import { Dashboard } from './chunk-MOAEEF5P.js';
2
+ export { Dashboard, DashboardCard, DashboardContext, DashboardDialog, DashboardEditor, DashboardLayout as DashboardLayoutComponent, DashboardList, DashboardProvider, DateRangeFilter, EditorToolbar, FilterBar, MultiSelectFilter, SelectFilter, TextFilter, Widget, WidgetContent, WidgetEditor, WidgetHeader, WidgetPalette, useAutoRefresh, useDashboard, useDashboardFilters, useFullscreen, useWidget } from './chunk-MOAEEF5P.js';
3
+ export { AreaChart, BarChart, EChartWrapper, LineChart, MetricCard, PieChart, ScatterChart, Sparkline, TrendIndicator, applyThemeToOption, createChartTheme, createGradientColor, dataPointsToChartData, formatAxisLabel, formatCompact, formatMetricValue, getChartColors, isChartDataEmpty, queryResultToChartData, suggestChartType, toChartData } from './chunk-2H5WTH4K.js';
4
+ import { useDashboardPinStatus, usePinMutations, usePinnedDashboards } from './chunk-UPYINBZU.js';
5
+ export { AggregationPicker, AnalyticsProvider, Badge, Button, Checkbox, ColumnNode, ColumnSelector, CustomSQLEditor, Dialog, DialogFooter, DialogHeader, Dropdown, DropdownItem, DropdownSeparator, EmptyDashboard, EmptyState, ErrorBoundary, ErrorFallback, FilterBuilder, FilterRow, FilterValueInput, Icon, Input, NoData, NoResults, Pagination, PrismiqClient, PrismiqError, QueryBuilder, QueryBuilderToolbar, QueryPreview, ResultsTable, SavedQueryPicker, SchemaExplorer, Select, SelectedColumn, Skeleton, SkeletonChart, SkeletonMetricCard, SkeletonTable, SkeletonText, SortBuilder, SortRow, TableCell, TableHeader, TableNode, TableRow, Tooltip, WidgetErrorBoundary, useAnalytics, useAnalyticsCallbacks, useChartData, useCustomSQL, useDashboard as useDashboardData, useDashboardMutations, useDashboardPinStatus, useDashboards, usePinMutations, usePinnedDashboards, useQuery, useSavedQueries, useSchema } from './chunk-UPYINBZU.js';
6
+ export { ThemeProvider, darkTheme, lightTheme, useTheme } from './chunk-T6STUE7E.js';
7
+ export { downloadFile, exportMultipleSheets, exportToCSV, exportToExcel, generateCSV, useExport } from './chunk-WWTT2OJ5.js';
8
+ export { BREAKPOINTS, ClientOnly, getLocalStorage, getWindowHeight, getWindowWidth, isBrowser, isServer, removeLocalStorage, setLocalStorage, useBreakpoint, useIsBreakpoint, useIsClient, useMediaQuery, useWindowSize } from './chunk-JTCBZDHY.js';
9
+ export { announceToScreenReader, focusVisibleStyles, skipLinkFocusStyles, skipLinkStyles, useArrowNavigation, useFocusTrap, useFocusVisible, useRovingTabIndex } from './chunk-EX74SI67.js';
10
+ import { useState, useCallback, useRef, useEffect } from 'react';
11
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
12
+
13
+ var PinIcon = ({ filled, size }) => /* @__PURE__ */ jsxs(
14
+ "svg",
15
+ {
16
+ width: size,
17
+ height: size,
18
+ viewBox: "0 0 24 24",
19
+ fill: filled ? "currentColor" : "none",
20
+ stroke: "currentColor",
21
+ strokeWidth: "2",
22
+ strokeLinecap: "round",
23
+ strokeLinejoin: "round",
24
+ children: [
25
+ /* @__PURE__ */ jsx("path", { d: "M12 17v5" }),
26
+ /* @__PURE__ */ jsx("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6a2 2 0 0 1 2-2h0a2 2 0 0 0 2-2H5a2 2 0 0 0 2 2h0a2 2 0 0 1 2 2z" })
27
+ ]
28
+ }
29
+ );
30
+ var baseStyles = {
31
+ display: "inline-flex",
32
+ alignItems: "center",
33
+ justifyContent: "center",
34
+ gap: "var(--prismiq-spacing-xs)",
35
+ fontFamily: "var(--prismiq-font-sans)",
36
+ fontWeight: 500,
37
+ borderRadius: "var(--prismiq-radius-md)",
38
+ border: "1px solid var(--prismiq-color-border)",
39
+ backgroundColor: "var(--prismiq-color-surface)",
40
+ color: "var(--prismiq-color-text)",
41
+ cursor: "pointer",
42
+ transition: "background-color 0.15s, border-color 0.15s, opacity 0.15s",
43
+ outline: "none"
44
+ };
45
+ var sizeStyles = {
46
+ sm: {
47
+ padding: "var(--prismiq-spacing-xs)",
48
+ fontSize: "var(--prismiq-font-size-sm)",
49
+ minWidth: 28,
50
+ minHeight: 28
51
+ },
52
+ md: {
53
+ padding: "var(--prismiq-spacing-sm)",
54
+ fontSize: "var(--prismiq-font-size-base)",
55
+ minWidth: 36,
56
+ minHeight: 36
57
+ },
58
+ lg: {
59
+ padding: "var(--prismiq-spacing-md)",
60
+ fontSize: "var(--prismiq-font-size-lg)",
61
+ minWidth: 44,
62
+ minHeight: 44
63
+ }
64
+ };
65
+ var pinnedStyles = {
66
+ backgroundColor: "var(--prismiq-color-primary-light, #e3f2fd)",
67
+ borderColor: "var(--prismiq-color-primary)",
68
+ color: "var(--prismiq-color-primary)"
69
+ };
70
+ var disabledStyles = {
71
+ opacity: 0.5,
72
+ cursor: "not-allowed"
73
+ };
74
+ var iconSizes = {
75
+ sm: 14,
76
+ md: 16,
77
+ lg: 20
78
+ };
79
+ function PinButton({
80
+ dashboardId,
81
+ context,
82
+ label = "Pin",
83
+ unpinLabel = "Unpin",
84
+ iconOnly = false,
85
+ size = "md",
86
+ onPinChange,
87
+ className,
88
+ style
89
+ }) {
90
+ const { isPinned: checkIsPinned, isLoading: statusLoading, refetch } = useDashboardPinStatus({
91
+ dashboardId
92
+ });
93
+ const { pin, unpin, state: mutationState } = usePinMutations();
94
+ const [actionError, setActionError] = useState(null);
95
+ const isPinned = checkIsPinned(context);
96
+ const isLoading = statusLoading || mutationState.isLoading;
97
+ const handleClick = useCallback(async () => {
98
+ if (isLoading) return;
99
+ setActionError(null);
100
+ try {
101
+ if (isPinned) {
102
+ await unpin(dashboardId, context);
103
+ onPinChange?.(false);
104
+ } else {
105
+ await pin(dashboardId, context);
106
+ onPinChange?.(true);
107
+ }
108
+ await refetch();
109
+ } catch (err) {
110
+ const error = err instanceof Error ? err : new Error(String(err));
111
+ setActionError(error);
112
+ console.error("Failed to toggle pin:", err);
113
+ }
114
+ }, [dashboardId, context, isPinned, isLoading, pin, unpin, onPinChange, refetch]);
115
+ const errorStyles2 = {
116
+ borderColor: "var(--prismiq-color-error)",
117
+ color: "var(--prismiq-color-error)"
118
+ };
119
+ const combinedStyles = {
120
+ ...baseStyles,
121
+ ...sizeStyles[size],
122
+ ...isPinned ? pinnedStyles : {},
123
+ ...isLoading ? disabledStyles : {},
124
+ ...actionError ? errorStyles2 : {},
125
+ ...style
126
+ };
127
+ const iconSize = iconSizes[size];
128
+ const displayLabel = isPinned ? unpinLabel : label;
129
+ const errorMessage = actionError ? `Error: ${actionError.message}` : void 0;
130
+ const accessibleLabel = errorMessage ?? (iconOnly ? displayLabel : void 0);
131
+ const tooltipTitle = errorMessage ?? (iconOnly ? displayLabel : void 0);
132
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
133
+ /* @__PURE__ */ jsx("style", { children: `
134
+ @keyframes prismiq-spin {
135
+ to {
136
+ transform: rotate(360deg);
137
+ }
138
+ }
139
+ ` }),
140
+ /* @__PURE__ */ jsxs(
141
+ "button",
142
+ {
143
+ type: "button",
144
+ onClick: handleClick,
145
+ disabled: isLoading,
146
+ className,
147
+ style: combinedStyles,
148
+ "aria-pressed": isPinned,
149
+ "aria-label": accessibleLabel,
150
+ "aria-invalid": actionError ? true : void 0,
151
+ title: tooltipTitle,
152
+ children: [
153
+ isLoading ? /* @__PURE__ */ jsx(
154
+ "span",
155
+ {
156
+ style: {
157
+ display: "inline-block",
158
+ width: iconSize,
159
+ height: iconSize,
160
+ border: "2px solid currentColor",
161
+ borderRightColor: "transparent",
162
+ borderRadius: "50%",
163
+ animation: "prismiq-spin 0.6s linear infinite"
164
+ }
165
+ }
166
+ ) : /* @__PURE__ */ jsx(PinIcon, { filled: isPinned, size: iconSize }),
167
+ !iconOnly && /* @__PURE__ */ jsx("span", { children: displayLabel })
168
+ ]
169
+ }
170
+ )
171
+ ] });
172
+ }
173
+ var errorBannerStyles = {
174
+ padding: "var(--prismiq-spacing-sm)",
175
+ backgroundColor: "var(--prismiq-color-error-light, #ffebee)",
176
+ color: "var(--prismiq-color-error)",
177
+ borderRadius: "var(--prismiq-radius-sm)",
178
+ fontFamily: "var(--prismiq-font-sans)",
179
+ fontSize: "var(--prismiq-font-size-xs)",
180
+ marginBottom: "var(--prismiq-spacing-xs)"
181
+ };
182
+ var PinIcon2 = ({ size }) => /* @__PURE__ */ jsxs(
183
+ "svg",
184
+ {
185
+ width: size,
186
+ height: size,
187
+ viewBox: "0 0 24 24",
188
+ fill: "none",
189
+ stroke: "currentColor",
190
+ strokeWidth: "2",
191
+ strokeLinecap: "round",
192
+ strokeLinejoin: "round",
193
+ children: [
194
+ /* @__PURE__ */ jsx("path", { d: "M12 17v5" }),
195
+ /* @__PURE__ */ jsx("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6a2 2 0 0 1 2-2h0a2 2 0 0 0 2-2H5a2 2 0 0 0 2 2h0a2 2 0 0 1 2 2z" })
196
+ ]
197
+ }
198
+ );
199
+ var ChevronDownIcon = ({ size }) => /* @__PURE__ */ jsx(
200
+ "svg",
201
+ {
202
+ width: size,
203
+ height: size,
204
+ viewBox: "0 0 24 24",
205
+ fill: "none",
206
+ stroke: "currentColor",
207
+ strokeWidth: "2",
208
+ strokeLinecap: "round",
209
+ strokeLinejoin: "round",
210
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
211
+ }
212
+ );
213
+ var CheckIcon = ({ size }) => /* @__PURE__ */ jsx(
214
+ "svg",
215
+ {
216
+ width: size,
217
+ height: size,
218
+ viewBox: "0 0 24 24",
219
+ fill: "none",
220
+ stroke: "currentColor",
221
+ strokeWidth: "2",
222
+ strokeLinecap: "round",
223
+ strokeLinejoin: "round",
224
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
225
+ }
226
+ );
227
+ var triggerStyles = {
228
+ display: "inline-flex",
229
+ alignItems: "center",
230
+ gap: "var(--prismiq-spacing-xs)",
231
+ padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
232
+ fontFamily: "var(--prismiq-font-sans)",
233
+ fontSize: "var(--prismiq-font-size-base)",
234
+ fontWeight: 500,
235
+ borderRadius: "var(--prismiq-radius-md)",
236
+ border: "1px solid var(--prismiq-color-border)",
237
+ backgroundColor: "var(--prismiq-color-surface)",
238
+ color: "var(--prismiq-color-text)",
239
+ cursor: "pointer",
240
+ transition: "background-color 0.15s, border-color 0.15s",
241
+ outline: "none"
242
+ };
243
+ var menuStyles = {
244
+ position: "absolute",
245
+ top: "100%",
246
+ left: 0,
247
+ marginTop: "var(--prismiq-spacing-xs)",
248
+ minWidth: 200,
249
+ padding: "var(--prismiq-spacing-xs)",
250
+ backgroundColor: "var(--prismiq-color-surface)",
251
+ border: "1px solid var(--prismiq-color-border)",
252
+ borderRadius: "var(--prismiq-radius-md)",
253
+ boxShadow: "var(--prismiq-shadow-lg, 0 10px 15px -3px rgba(0,0,0,0.1))",
254
+ zIndex: 50
255
+ };
256
+ var menuItemStyles = {
257
+ display: "flex",
258
+ alignItems: "center",
259
+ gap: "var(--prismiq-spacing-sm)",
260
+ padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
261
+ fontFamily: "var(--prismiq-font-sans)",
262
+ fontSize: "var(--prismiq-font-size-sm)",
263
+ color: "var(--prismiq-color-text)",
264
+ borderRadius: "var(--prismiq-radius-sm)",
265
+ cursor: "pointer",
266
+ transition: "background-color 0.15s",
267
+ border: "none",
268
+ backgroundColor: "transparent",
269
+ width: "100%",
270
+ textAlign: "left"
271
+ };
272
+ var checkboxStyles = {
273
+ width: 16,
274
+ height: 16,
275
+ display: "flex",
276
+ alignItems: "center",
277
+ justifyContent: "center",
278
+ borderRadius: "var(--prismiq-radius-sm)",
279
+ border: "1px solid var(--prismiq-color-border)",
280
+ backgroundColor: "var(--prismiq-color-surface)",
281
+ flexShrink: 0
282
+ };
283
+ var checkedCheckboxStyles = {
284
+ ...checkboxStyles,
285
+ backgroundColor: "var(--prismiq-color-primary)",
286
+ borderColor: "var(--prismiq-color-primary)",
287
+ color: "var(--prismiq-color-text-inverse)"
288
+ };
289
+ function PinMenu({
290
+ dashboardId,
291
+ contexts,
292
+ onPinChange,
293
+ className,
294
+ style
295
+ }) {
296
+ const [isOpen, setIsOpen] = useState(false);
297
+ const [toggleError, setToggleError] = useState(null);
298
+ const containerRef = useRef(null);
299
+ const { isPinned, refetch, isLoading: statusLoading } = useDashboardPinStatus({
300
+ dashboardId
301
+ });
302
+ const { pin, unpin, state: mutationState } = usePinMutations();
303
+ const isLoading = statusLoading || mutationState.isLoading;
304
+ useEffect(() => {
305
+ if (!isOpen) {
306
+ setToggleError(null);
307
+ }
308
+ }, [isOpen]);
309
+ useEffect(() => {
310
+ const handleClickOutside = (event) => {
311
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
312
+ setIsOpen(false);
313
+ }
314
+ };
315
+ if (isOpen) {
316
+ document.addEventListener("mousedown", handleClickOutside);
317
+ return () => document.removeEventListener("mousedown", handleClickOutside);
318
+ }
319
+ }, [isOpen]);
320
+ useEffect(() => {
321
+ const handleEscape = (event) => {
322
+ if (event.key === "Escape") {
323
+ setIsOpen(false);
324
+ }
325
+ };
326
+ if (isOpen) {
327
+ document.addEventListener("keydown", handleEscape);
328
+ return () => document.removeEventListener("keydown", handleEscape);
329
+ }
330
+ }, [isOpen]);
331
+ const handleToggle = useCallback((ctx) => {
332
+ return async () => {
333
+ if (isLoading) return;
334
+ setToggleError(null);
335
+ try {
336
+ const pinned = isPinned(ctx);
337
+ if (pinned) {
338
+ await unpin(dashboardId, ctx);
339
+ onPinChange?.(ctx, false);
340
+ } else {
341
+ await pin(dashboardId, ctx);
342
+ onPinChange?.(ctx, true);
343
+ }
344
+ await refetch();
345
+ } catch (err) {
346
+ const error = err instanceof Error ? err : new Error(String(err));
347
+ setToggleError(error);
348
+ console.error("Failed to toggle pin for context:", ctx, err);
349
+ }
350
+ };
351
+ }, [dashboardId, isPinned, isLoading, pin, unpin, onPinChange, refetch]);
352
+ const pinnedCount = contexts.filter((ctx) => isPinned(ctx.id)).length;
353
+ return /* @__PURE__ */ jsxs(
354
+ "div",
355
+ {
356
+ ref: containerRef,
357
+ className,
358
+ style: { position: "relative", display: "inline-block", ...style },
359
+ children: [
360
+ /* @__PURE__ */ jsxs(
361
+ "button",
362
+ {
363
+ type: "button",
364
+ onClick: () => setIsOpen(!isOpen),
365
+ style: triggerStyles,
366
+ "aria-haspopup": "menu",
367
+ "aria-expanded": isOpen,
368
+ children: [
369
+ /* @__PURE__ */ jsx(PinIcon2, { size: 16 }),
370
+ /* @__PURE__ */ jsxs("span", { children: [
371
+ "Pin",
372
+ pinnedCount > 0 ? ` (${pinnedCount})` : ""
373
+ ] }),
374
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: 14 })
375
+ ]
376
+ }
377
+ ),
378
+ isOpen && /* @__PURE__ */ jsxs("div", { style: menuStyles, role: "menu", children: [
379
+ toggleError && /* @__PURE__ */ jsxs("div", { style: errorBannerStyles, children: [
380
+ "Failed: ",
381
+ toggleError.message
382
+ ] }),
383
+ contexts.map((ctx) => {
384
+ const pinned = isPinned(ctx.id);
385
+ return /* @__PURE__ */ jsxs(
386
+ "button",
387
+ {
388
+ type: "button",
389
+ role: "menuitemcheckbox",
390
+ "aria-checked": pinned,
391
+ onClick: handleToggle(ctx.id),
392
+ disabled: isLoading,
393
+ style: {
394
+ ...menuItemStyles,
395
+ opacity: isLoading ? 0.5 : 1
396
+ },
397
+ children: [
398
+ /* @__PURE__ */ jsx("span", { style: pinned ? checkedCheckboxStyles : checkboxStyles, children: pinned && /* @__PURE__ */ jsx(CheckIcon, { size: 12 }) }),
399
+ ctx.icon && /* @__PURE__ */ jsx("span", { style: { display: "flex" }, children: ctx.icon }),
400
+ /* @__PURE__ */ jsx("span", { children: ctx.label })
401
+ ]
402
+ },
403
+ ctx.id
404
+ );
405
+ })
406
+ ] })
407
+ ]
408
+ }
409
+ );
410
+ }
411
+ var DashboardIcon = () => /* @__PURE__ */ jsxs(
412
+ "svg",
413
+ {
414
+ width: 20,
415
+ height: 20,
416
+ viewBox: "0 0 24 24",
417
+ fill: "none",
418
+ stroke: "currentColor",
419
+ strokeWidth: "2",
420
+ strokeLinecap: "round",
421
+ strokeLinejoin: "round",
422
+ children: [
423
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7" }),
424
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "3", width: "7", height: "7" }),
425
+ /* @__PURE__ */ jsx("rect", { x: "14", y: "14", width: "7", height: "7" }),
426
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "14", width: "7", height: "7" })
427
+ ]
428
+ }
429
+ );
430
+ var UnpinIcon = () => /* @__PURE__ */ jsxs(
431
+ "svg",
432
+ {
433
+ width: 16,
434
+ height: 16,
435
+ viewBox: "0 0 24 24",
436
+ fill: "none",
437
+ stroke: "currentColor",
438
+ strokeWidth: "2",
439
+ strokeLinecap: "round",
440
+ strokeLinejoin: "round",
441
+ children: [
442
+ /* @__PURE__ */ jsx("path", { d: "M2 2 22 22" }),
443
+ /* @__PURE__ */ jsx("path", { d: "M12 17v5" }),
444
+ /* @__PURE__ */ jsx("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9" }),
445
+ /* @__PURE__ */ jsx("path", { d: "M15 6V4a2 2 0 0 1 2-2" }),
446
+ /* @__PURE__ */ jsx("path", { d: "M9 4a2 2 0 0 0-2 2" })
447
+ ]
448
+ }
449
+ );
450
+ var containerStyles = {
451
+ display: "flex",
452
+ flexDirection: "column",
453
+ gap: "var(--prismiq-spacing-sm)"
454
+ };
455
+ var itemStyles = {
456
+ display: "flex",
457
+ alignItems: "center",
458
+ gap: "var(--prismiq-spacing-md)",
459
+ padding: "var(--prismiq-spacing-md)",
460
+ backgroundColor: "var(--prismiq-color-surface)",
461
+ border: "1px solid var(--prismiq-color-border)",
462
+ borderRadius: "var(--prismiq-radius-md)",
463
+ cursor: "pointer",
464
+ transition: "background-color 0.15s, border-color 0.15s, box-shadow 0.15s"
465
+ };
466
+ var itemHoverStyles = {
467
+ backgroundColor: "var(--prismiq-color-surface-hover, #f5f5f5)",
468
+ borderColor: "var(--prismiq-color-primary)",
469
+ boxShadow: "var(--prismiq-shadow-sm, 0 1px 2px rgba(0,0,0,0.05))"
470
+ };
471
+ var iconWrapperStyles = {
472
+ display: "flex",
473
+ alignItems: "center",
474
+ justifyContent: "center",
475
+ width: 40,
476
+ height: 40,
477
+ backgroundColor: "var(--prismiq-color-primary-light, #e3f2fd)",
478
+ color: "var(--prismiq-color-primary)",
479
+ borderRadius: "var(--prismiq-radius-md)",
480
+ flexShrink: 0
481
+ };
482
+ var contentStyles = {
483
+ flex: 1,
484
+ minWidth: 0
485
+ };
486
+ var titleStyles = {
487
+ fontFamily: "var(--prismiq-font-sans)",
488
+ fontSize: "var(--prismiq-font-size-base)",
489
+ fontWeight: 500,
490
+ color: "var(--prismiq-color-text)",
491
+ margin: 0,
492
+ overflow: "hidden",
493
+ textOverflow: "ellipsis",
494
+ whiteSpace: "nowrap"
495
+ };
496
+ var descriptionStyles = {
497
+ fontFamily: "var(--prismiq-font-sans)",
498
+ fontSize: "var(--prismiq-font-size-sm)",
499
+ color: "var(--prismiq-color-text-muted)",
500
+ margin: 0,
501
+ marginTop: "var(--prismiq-spacing-xs)",
502
+ overflow: "hidden",
503
+ textOverflow: "ellipsis",
504
+ whiteSpace: "nowrap"
505
+ };
506
+ var unpinButtonStyles = {
507
+ display: "flex",
508
+ alignItems: "center",
509
+ justifyContent: "center",
510
+ width: 32,
511
+ height: 32,
512
+ padding: 0,
513
+ backgroundColor: "transparent",
514
+ border: "1px solid transparent",
515
+ borderRadius: "var(--prismiq-radius-sm)",
516
+ color: "var(--prismiq-color-text-muted)",
517
+ cursor: "pointer",
518
+ transition: "background-color 0.15s, color 0.15s",
519
+ flexShrink: 0
520
+ };
521
+ var emptyStateStyles = {
522
+ display: "flex",
523
+ flexDirection: "column",
524
+ alignItems: "center",
525
+ justifyContent: "center",
526
+ padding: "var(--prismiq-spacing-xl)",
527
+ textAlign: "center",
528
+ color: "var(--prismiq-color-text-muted)"
529
+ };
530
+ var loadingStyles = {
531
+ display: "flex",
532
+ alignItems: "center",
533
+ justifyContent: "center",
534
+ padding: "var(--prismiq-spacing-xl)"
535
+ };
536
+ var errorStyles = {
537
+ padding: "var(--prismiq-spacing-md)",
538
+ backgroundColor: "var(--prismiq-color-error-light, #ffebee)",
539
+ color: "var(--prismiq-color-error)",
540
+ borderRadius: "var(--prismiq-radius-md)",
541
+ fontFamily: "var(--prismiq-font-sans)",
542
+ fontSize: "var(--prismiq-font-size-sm)"
543
+ };
544
+ function PinnedDashboardList({
545
+ context,
546
+ onSelect,
547
+ emptyState,
548
+ renderItem,
549
+ className,
550
+ style
551
+ }) {
552
+ const { dashboards, isLoading, error, refetch } = usePinnedDashboards({ context });
553
+ const { unpin, state: mutationState } = usePinMutations();
554
+ const [unpinError, setUnpinError] = useState(null);
555
+ const handleUnpin = useCallback(
556
+ (dashboardId) => {
557
+ return async (event) => {
558
+ event.stopPropagation();
559
+ setUnpinError(null);
560
+ try {
561
+ await unpin(dashboardId, context);
562
+ await refetch();
563
+ } catch (err) {
564
+ const error2 = err instanceof Error ? err : new Error(String(err));
565
+ setUnpinError(error2);
566
+ console.error("Failed to unpin dashboard:", dashboardId, err);
567
+ }
568
+ };
569
+ },
570
+ [context, unpin, refetch]
571
+ );
572
+ const createUnpinAction = useCallback(
573
+ (dashboardId) => {
574
+ return async () => {
575
+ setUnpinError(null);
576
+ try {
577
+ await unpin(dashboardId, context);
578
+ await refetch();
579
+ } catch (err) {
580
+ const error2 = err instanceof Error ? err : new Error(String(err));
581
+ setUnpinError(error2);
582
+ console.error("Failed to unpin dashboard:", dashboardId, err);
583
+ throw error2;
584
+ }
585
+ };
586
+ },
587
+ [context, unpin, refetch]
588
+ );
589
+ if (isLoading) {
590
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...containerStyles, ...style }, children: [
591
+ /* @__PURE__ */ jsx("style", { children: `
592
+ @keyframes prismiq-spin {
593
+ to {
594
+ transform: rotate(360deg);
595
+ }
596
+ }
597
+ ` }),
598
+ /* @__PURE__ */ jsx("div", { style: loadingStyles, children: /* @__PURE__ */ jsx(
599
+ "span",
600
+ {
601
+ style: {
602
+ display: "inline-block",
603
+ width: 24,
604
+ height: 24,
605
+ border: "2px solid var(--prismiq-color-border)",
606
+ borderTopColor: "var(--prismiq-color-primary)",
607
+ borderRadius: "50%",
608
+ animation: "prismiq-spin 0.6s linear infinite"
609
+ }
610
+ }
611
+ ) })
612
+ ] });
613
+ }
614
+ if (error) {
615
+ return /* @__PURE__ */ jsx("div", { className, style: { ...containerStyles, ...style }, children: /* @__PURE__ */ jsxs("div", { style: errorStyles, children: [
616
+ "Failed to load pinned dashboards: ",
617
+ error.message
618
+ ] }) });
619
+ }
620
+ const errorBanner = unpinError ? /* @__PURE__ */ jsxs("div", { style: { ...errorStyles, display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
621
+ /* @__PURE__ */ jsxs("span", { children: [
622
+ "Failed to unpin: ",
623
+ unpinError.message
624
+ ] }),
625
+ /* @__PURE__ */ jsx(
626
+ "button",
627
+ {
628
+ type: "button",
629
+ onClick: () => setUnpinError(null),
630
+ style: {
631
+ background: "none",
632
+ border: "none",
633
+ cursor: "pointer",
634
+ color: "inherit",
635
+ fontSize: "var(--prismiq-font-size-lg)",
636
+ lineHeight: 1
637
+ },
638
+ "aria-label": "Dismiss error",
639
+ children: "\xD7"
640
+ }
641
+ )
642
+ ] }) : null;
643
+ if (!dashboards || dashboards.length === 0) {
644
+ return /* @__PURE__ */ jsx("div", { className, style: { ...containerStyles, ...style }, children: emptyState || /* @__PURE__ */ jsxs("div", { style: emptyStateStyles, children: [
645
+ /* @__PURE__ */ jsx(DashboardIcon, {}),
646
+ /* @__PURE__ */ jsx("p", { style: { margin: "var(--prismiq-spacing-sm) 0 0 0" }, children: "No pinned dashboards" })
647
+ ] }) });
648
+ }
649
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...containerStyles, ...style }, children: [
650
+ errorBanner,
651
+ dashboards.map((dashboard) => {
652
+ const actions = {
653
+ unpin: createUnpinAction(dashboard.id)
654
+ };
655
+ if (renderItem) {
656
+ return /* @__PURE__ */ jsx(
657
+ "div",
658
+ {
659
+ onClick: () => onSelect(dashboard),
660
+ role: "button",
661
+ tabIndex: 0,
662
+ onKeyDown: (e) => {
663
+ if (e.key === "Enter" || e.key === " ") {
664
+ e.preventDefault();
665
+ onSelect(dashboard);
666
+ }
667
+ },
668
+ children: renderItem(dashboard, actions)
669
+ },
670
+ dashboard.id
671
+ );
672
+ }
673
+ return /* @__PURE__ */ jsxs(
674
+ "div",
675
+ {
676
+ style: itemStyles,
677
+ onClick: () => onSelect(dashboard),
678
+ onMouseEnter: (e) => {
679
+ Object.assign(e.currentTarget.style, itemHoverStyles);
680
+ },
681
+ onMouseLeave: (e) => {
682
+ Object.assign(e.currentTarget.style, itemStyles);
683
+ },
684
+ role: "button",
685
+ tabIndex: 0,
686
+ onKeyDown: (e) => {
687
+ if (e.key === "Enter" || e.key === " ") {
688
+ e.preventDefault();
689
+ onSelect(dashboard);
690
+ }
691
+ },
692
+ children: [
693
+ /* @__PURE__ */ jsx("div", { style: iconWrapperStyles, children: /* @__PURE__ */ jsx(DashboardIcon, {}) }),
694
+ /* @__PURE__ */ jsxs("div", { style: contentStyles, children: [
695
+ /* @__PURE__ */ jsx("h3", { style: titleStyles, children: dashboard.name }),
696
+ dashboard.description && /* @__PURE__ */ jsx("p", { style: descriptionStyles, children: dashboard.description })
697
+ ] }),
698
+ /* @__PURE__ */ jsx(
699
+ "button",
700
+ {
701
+ type: "button",
702
+ onClick: handleUnpin(dashboard.id),
703
+ disabled: mutationState.isLoading,
704
+ style: {
705
+ ...unpinButtonStyles,
706
+ opacity: mutationState.isLoading ? 0.5 : 1
707
+ },
708
+ title: "Unpin",
709
+ "aria-label": "Unpin dashboard",
710
+ children: /* @__PURE__ */ jsx(UnpinIcon, {})
711
+ }
712
+ )
713
+ ]
714
+ },
715
+ dashboard.id
716
+ );
717
+ })
718
+ ] });
719
+ }
720
+ var BackIcon = () => /* @__PURE__ */ jsxs(
721
+ "svg",
722
+ {
723
+ width: 20,
724
+ height: 20,
725
+ viewBox: "0 0 24 24",
726
+ fill: "none",
727
+ stroke: "currentColor",
728
+ strokeWidth: "2",
729
+ strokeLinecap: "round",
730
+ strokeLinejoin: "round",
731
+ children: [
732
+ /* @__PURE__ */ jsx("path", { d: "M19 12H5" }),
733
+ /* @__PURE__ */ jsx("path", { d: "m12 19-7-7 7-7" })
734
+ ]
735
+ }
736
+ );
737
+ var UnpinIcon2 = () => /* @__PURE__ */ jsxs(
738
+ "svg",
739
+ {
740
+ width: 16,
741
+ height: 16,
742
+ viewBox: "0 0 24 24",
743
+ fill: "none",
744
+ stroke: "currentColor",
745
+ strokeWidth: "2",
746
+ strokeLinecap: "round",
747
+ strokeLinejoin: "round",
748
+ children: [
749
+ /* @__PURE__ */ jsx("path", { d: "M2 2 22 22" }),
750
+ /* @__PURE__ */ jsx("path", { d: "M12 17v5" }),
751
+ /* @__PURE__ */ jsx("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9" }),
752
+ /* @__PURE__ */ jsx("path", { d: "M15 6V4a2 2 0 0 1 2-2" }),
753
+ /* @__PURE__ */ jsx("path", { d: "M9 4a2 2 0 0 0-2 2" })
754
+ ]
755
+ }
756
+ );
757
+ var containerStyles2 = {
758
+ display: "flex",
759
+ flexDirection: "column",
760
+ height: "100%"
761
+ };
762
+ var headerStyles = {
763
+ display: "flex",
764
+ alignItems: "center",
765
+ gap: "var(--prismiq-spacing-md)",
766
+ padding: "var(--prismiq-spacing-md)",
767
+ borderBottom: "1px solid var(--prismiq-color-border)",
768
+ backgroundColor: "var(--prismiq-color-surface)"
769
+ };
770
+ var backButtonStyles = {
771
+ display: "flex",
772
+ alignItems: "center",
773
+ gap: "var(--prismiq-spacing-xs)",
774
+ padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
775
+ fontFamily: "var(--prismiq-font-sans)",
776
+ fontSize: "var(--prismiq-font-size-sm)",
777
+ fontWeight: 500,
778
+ backgroundColor: "transparent",
779
+ border: "1px solid var(--prismiq-color-border)",
780
+ borderRadius: "var(--prismiq-radius-md)",
781
+ color: "var(--prismiq-color-text)",
782
+ cursor: "pointer",
783
+ transition: "background-color 0.15s"
784
+ };
785
+ var titleStyles2 = {
786
+ flex: 1,
787
+ fontFamily: "var(--prismiq-font-sans)",
788
+ fontSize: "var(--prismiq-font-size-lg)",
789
+ fontWeight: 600,
790
+ color: "var(--prismiq-color-text)",
791
+ margin: 0,
792
+ overflow: "hidden",
793
+ textOverflow: "ellipsis",
794
+ whiteSpace: "nowrap"
795
+ };
796
+ var unpinButtonStyles2 = {
797
+ display: "flex",
798
+ alignItems: "center",
799
+ gap: "var(--prismiq-spacing-xs)",
800
+ padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
801
+ fontFamily: "var(--prismiq-font-sans)",
802
+ fontSize: "var(--prismiq-font-size-sm)",
803
+ backgroundColor: "transparent",
804
+ border: "1px solid var(--prismiq-color-border)",
805
+ borderRadius: "var(--prismiq-radius-md)",
806
+ color: "var(--prismiq-color-text-muted)",
807
+ cursor: "pointer",
808
+ transition: "background-color 0.15s, color 0.15s"
809
+ };
810
+ var contentStyles2 = {
811
+ flex: 1,
812
+ overflow: "auto"
813
+ };
814
+ var listContainerStyles = {
815
+ padding: "var(--prismiq-spacing-md)"
816
+ };
817
+ var errorBannerStyles2 = {
818
+ padding: "var(--prismiq-spacing-sm) var(--prismiq-spacing-md)",
819
+ backgroundColor: "var(--prismiq-color-error-light, #ffebee)",
820
+ color: "var(--prismiq-color-error)",
821
+ fontFamily: "var(--prismiq-font-sans)",
822
+ fontSize: "var(--prismiq-font-size-sm)",
823
+ display: "flex",
824
+ justifyContent: "space-between",
825
+ alignItems: "center"
826
+ };
827
+ function PinnedDashboardView({
828
+ context,
829
+ selectedDashboard,
830
+ onBack,
831
+ onSelect,
832
+ showUnpin = true,
833
+ backLabel = "Back",
834
+ emptyState,
835
+ className,
836
+ style
837
+ }) {
838
+ const { unpin, state: mutationState } = usePinMutations();
839
+ const [unpinError, setUnpinError] = useState(null);
840
+ const handleUnpin = async () => {
841
+ if (!selectedDashboard) return;
842
+ setUnpinError(null);
843
+ try {
844
+ await unpin(selectedDashboard.id, context);
845
+ onBack();
846
+ } catch (err) {
847
+ const error = err instanceof Error ? err : new Error(String(err));
848
+ setUnpinError(error);
849
+ console.error("Failed to unpin dashboard:", selectedDashboard.id, err);
850
+ }
851
+ };
852
+ if (!selectedDashboard) {
853
+ return /* @__PURE__ */ jsx("div", { className, style: { ...containerStyles2, ...style }, children: /* @__PURE__ */ jsx("div", { style: listContainerStyles, children: /* @__PURE__ */ jsx(
854
+ PinnedDashboardList,
855
+ {
856
+ context,
857
+ onSelect,
858
+ emptyState
859
+ }
860
+ ) }) });
861
+ }
862
+ return /* @__PURE__ */ jsxs("div", { className, style: { ...containerStyles2, ...style }, children: [
863
+ unpinError && /* @__PURE__ */ jsxs("div", { style: errorBannerStyles2, children: [
864
+ /* @__PURE__ */ jsxs("span", { children: [
865
+ "Failed to unpin: ",
866
+ unpinError.message
867
+ ] }),
868
+ /* @__PURE__ */ jsx(
869
+ "button",
870
+ {
871
+ type: "button",
872
+ onClick: () => setUnpinError(null),
873
+ style: {
874
+ background: "none",
875
+ border: "none",
876
+ cursor: "pointer",
877
+ color: "inherit",
878
+ fontSize: "var(--prismiq-font-size-lg)",
879
+ lineHeight: 1
880
+ },
881
+ "aria-label": "Dismiss error",
882
+ children: "\xD7"
883
+ }
884
+ )
885
+ ] }),
886
+ /* @__PURE__ */ jsxs("div", { style: headerStyles, children: [
887
+ /* @__PURE__ */ jsxs(
888
+ "button",
889
+ {
890
+ type: "button",
891
+ onClick: onBack,
892
+ style: backButtonStyles,
893
+ children: [
894
+ /* @__PURE__ */ jsx(BackIcon, {}),
895
+ /* @__PURE__ */ jsx("span", { children: backLabel })
896
+ ]
897
+ }
898
+ ),
899
+ /* @__PURE__ */ jsx("h2", { style: titleStyles2, children: selectedDashboard.name }),
900
+ showUnpin && /* @__PURE__ */ jsxs(
901
+ "button",
902
+ {
903
+ type: "button",
904
+ onClick: handleUnpin,
905
+ disabled: mutationState.isLoading,
906
+ style: {
907
+ ...unpinButtonStyles2,
908
+ opacity: mutationState.isLoading ? 0.5 : 1
909
+ },
910
+ children: [
911
+ /* @__PURE__ */ jsx(UnpinIcon2, {}),
912
+ /* @__PURE__ */ jsx("span", { children: "Unpin" })
913
+ ]
914
+ }
915
+ )
916
+ ] }),
917
+ /* @__PURE__ */ jsx("div", { style: contentStyles2, children: /* @__PURE__ */ jsx(Dashboard, { id: selectedDashboard.id }) })
918
+ ] });
919
+ }
920
+
921
+ // src/index.ts
922
+ var VERSION = "0.1.0";
923
+
924
+ export { PinButton, PinMenu, PinnedDashboardList, PinnedDashboardView, VERSION };
925
+ //# sourceMappingURL=index.js.map
926
+ //# sourceMappingURL=index.js.map