drizzle-cube 0.4.40 → 0.4.42

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 (166) hide show
  1. package/dist/cli/index.cjs +439 -0
  2. package/dist/client/charts/ChartLoader.d.ts +18 -3
  3. package/dist/client/charts/chartConfigRegistry.d.ts +11 -1
  4. package/dist/client/charts/chartPlugin.d.ts +74 -0
  5. package/dist/client/charts/lazyChartConfigRegistry.d.ts +10 -0
  6. package/dist/client/charts.js +13 -15
  7. package/dist/client/chunks/{DashboardEditModal-iGhIvNP6.js → DashboardEditModal-4zzjtZRR.js} +683 -685
  8. package/dist/client/chunks/DashboardEditModal-4zzjtZRR.js.map +1 -0
  9. package/dist/client/chunks/{FieldSearchModal-BxQ5JhWz.js → FieldSearchModal-trURu9Sa.js} +15 -16
  10. package/dist/client/chunks/{FieldSearchModal-BxQ5JhWz.js.map → FieldSearchModal-trURu9Sa.js.map} +1 -1
  11. package/dist/client/chunks/{RetentionCombinedChart-D4Yf1TnQ.js → RetentionCombinedChart-B1hUYaXt.js} +2 -2
  12. package/dist/client/chunks/{RetentionCombinedChart-D4Yf1TnQ.js.map → RetentionCombinedChart-B1hUYaXt.js.map} +1 -1
  13. package/dist/client/chunks/{RetentionHeatmap-BoGY6mlZ.js → RetentionHeatmap-Dn2ocjVf.js} +2 -2
  14. package/dist/client/chunks/{RetentionHeatmap-BoGY6mlZ.js.map → RetentionHeatmap-Dn2ocjVf.js.map} +1 -1
  15. package/dist/client/chunks/{analysis-builder-DEGG5NwE.js → analysis-builder-B7XSIMkr.js} +1474 -1523
  16. package/dist/client/chunks/analysis-builder-B7XSIMkr.js.map +1 -0
  17. package/dist/client/chunks/{analysis-builder-shared-BxHYfTzo.js → analysis-builder-shared-DaqtrLxd.js} +762 -778
  18. package/dist/client/chunks/analysis-builder-shared-DaqtrLxd.js.map +1 -0
  19. package/dist/client/chunks/{chart-bar-Bx4oKlqo.js → chart-bar-CPt67rLR.js} +1 -1
  20. package/dist/client/chunks/{chart-bar-Bx4oKlqo.js.map → chart-bar-CPt67rLR.js.map} +1 -1
  21. package/dist/client/chunks/{chart-box-plot-CVIi1aM5.js → chart-box-plot-Dp_nqQen.js} +1 -1
  22. package/dist/client/chunks/{chart-box-plot-CVIi1aM5.js.map → chart-box-plot-Dp_nqQen.js.map} +1 -1
  23. package/dist/client/chunks/{chart-bubble-DvyG15UB.js → chart-bubble-CYQ8loeS.js} +1 -1
  24. package/dist/client/chunks/{chart-bubble-DvyG15UB.js.map → chart-bubble-CYQ8loeS.js.map} +1 -1
  25. package/dist/client/chunks/{chart-candlestick-caHyxB9O.js → chart-candlestick-DTeSf7C5.js} +1 -1
  26. package/dist/client/chunks/{chart-candlestick-caHyxB9O.js.map → chart-candlestick-DTeSf7C5.js.map} +1 -1
  27. package/dist/client/chunks/{chart-config-activity-grid-USo7JrPh.js → chart-config-activity-grid-BSWS08cI.js} +1 -1
  28. package/dist/client/chunks/{chart-config-activity-grid-USo7JrPh.js.map → chart-config-activity-grid-BSWS08cI.js.map} +1 -1
  29. package/dist/client/chunks/{chart-config-area-D_ZufYzg.js → chart-config-area-DKwgcHp4.js} +1 -1
  30. package/dist/client/chunks/{chart-config-area-D_ZufYzg.js.map → chart-config-area-DKwgcHp4.js.map} +1 -1
  31. package/dist/client/chunks/{chart-config-bar-BCi2Wmd6.js → chart-config-bar-deTjEhap.js} +1 -1
  32. package/dist/client/chunks/{chart-config-bar-BCi2Wmd6.js.map → chart-config-bar-deTjEhap.js.map} +1 -1
  33. package/dist/client/chunks/{chart-config-box-plot-afKLzJSp.js → chart-config-box-plot-DU4iWk3V.js} +1 -1
  34. package/dist/client/chunks/{chart-config-box-plot-afKLzJSp.js.map → chart-config-box-plot-DU4iWk3V.js.map} +1 -1
  35. package/dist/client/chunks/{chart-config-bubble-CgbBjPv8.js → chart-config-bubble-B8FSHSW-.js} +1 -1
  36. package/dist/client/chunks/{chart-config-bubble-CgbBjPv8.js.map → chart-config-bubble-B8FSHSW-.js.map} +1 -1
  37. package/dist/client/chunks/{chart-config-candlestick-7boGjZ-A.js → chart-config-candlestick-BGfyWFft.js} +1 -1
  38. package/dist/client/chunks/{chart-config-candlestick-7boGjZ-A.js.map → chart-config-candlestick-BGfyWFft.js.map} +1 -1
  39. package/dist/client/chunks/{chart-config-data-table-Cl7sBasW.js → chart-config-data-table-DKRcGa8t.js} +1 -1
  40. package/dist/client/chunks/{chart-config-data-table-Cl7sBasW.js.map → chart-config-data-table-DKRcGa8t.js.map} +1 -1
  41. package/dist/client/chunks/{chart-config-funnel-CXPYQtTl.js → chart-config-funnel-Bt4iGFo_.js} +1 -1
  42. package/dist/client/chunks/{chart-config-funnel-CXPYQtTl.js.map → chart-config-funnel-Bt4iGFo_.js.map} +1 -1
  43. package/dist/client/chunks/{chart-config-gauge-DUNEUCvh.js → chart-config-gauge-Bk4Jjp3W.js} +1 -1
  44. package/dist/client/chunks/{chart-config-gauge-DUNEUCvh.js.map → chart-config-gauge-Bk4Jjp3W.js.map} +1 -1
  45. package/dist/client/chunks/{chart-config-heat-map-BFf1tO11.js → chart-config-heat-map-CkHsqkrY.js} +1 -1
  46. package/dist/client/chunks/{chart-config-heat-map-BFf1tO11.js.map → chart-config-heat-map-CkHsqkrY.js.map} +1 -1
  47. package/dist/client/chunks/{chart-config-kpi-delta-C5k2waIJ.js → chart-config-kpi-delta-CkUX98JV.js} +1 -1
  48. package/dist/client/chunks/{chart-config-kpi-delta-C5k2waIJ.js.map → chart-config-kpi-delta-CkUX98JV.js.map} +1 -1
  49. package/dist/client/chunks/{chart-config-kpi-number-DptOyhk0.js → chart-config-kpi-number-DcxyiUgs.js} +1 -1
  50. package/dist/client/chunks/{chart-config-kpi-number-DptOyhk0.js.map → chart-config-kpi-number-DcxyiUgs.js.map} +1 -1
  51. package/dist/client/chunks/{chart-config-kpi-text-D9DdVWqd.js → chart-config-kpi-text-DI4mj8CN.js} +1 -1
  52. package/dist/client/chunks/{chart-config-kpi-text-D9DdVWqd.js.map → chart-config-kpi-text-DI4mj8CN.js.map} +1 -1
  53. package/dist/client/chunks/{chart-config-line-B3NgLF7K.js → chart-config-line--j7-dLue.js} +1 -1
  54. package/dist/client/chunks/{chart-config-line-B3NgLF7K.js.map → chart-config-line--j7-dLue.js.map} +1 -1
  55. package/dist/client/chunks/{chart-config-markdown-tlfivQTt.js → chart-config-markdown-DUjvVjV4.js} +1 -1
  56. package/dist/client/chunks/{chart-config-markdown-tlfivQTt.js.map → chart-config-markdown-DUjvVjV4.js.map} +1 -1
  57. package/dist/client/chunks/{chart-config-measure-profile-D7XDwrU2.js → chart-config-measure-profile-B9FKBNGc.js} +1 -1
  58. package/dist/client/chunks/{chart-config-measure-profile-D7XDwrU2.js.map → chart-config-measure-profile-B9FKBNGc.js.map} +1 -1
  59. package/dist/client/chunks/{chart-config-pie-wY0B52PC.js → chart-config-pie-yU4jipl9.js} +1 -1
  60. package/dist/client/chunks/{chart-config-pie-wY0B52PC.js.map → chart-config-pie-yU4jipl9.js.map} +1 -1
  61. package/dist/client/chunks/{chart-config-radar-DRpJBy1M.js → chart-config-radar-R9Fkc8wL.js} +1 -1
  62. package/dist/client/chunks/{chart-config-radar-DRpJBy1M.js.map → chart-config-radar-R9Fkc8wL.js.map} +1 -1
  63. package/dist/client/chunks/{chart-config-radial-bar-DCUpXv9G.js → chart-config-radial-bar-DeoXfpIp.js} +1 -1
  64. package/dist/client/chunks/{chart-config-radial-bar-DCUpXv9G.js.map → chart-config-radial-bar-DeoXfpIp.js.map} +1 -1
  65. package/dist/client/chunks/{chart-config-sankey-CdOhlm4h.js → chart-config-sankey-CXEsxo6s.js} +1 -1
  66. package/dist/client/chunks/{chart-config-sankey-CdOhlm4h.js.map → chart-config-sankey-CXEsxo6s.js.map} +1 -1
  67. package/dist/client/chunks/{chart-config-scatter-B2su_x8f.js → chart-config-scatter-MVUFupub.js} +1 -1
  68. package/dist/client/chunks/{chart-config-scatter-B2su_x8f.js.map → chart-config-scatter-MVUFupub.js.map} +1 -1
  69. package/dist/client/chunks/{chart-config-sunburst-BPdjbk18.js → chart-config-sunburst-Z_gqIY5u.js} +1 -1
  70. package/dist/client/chunks/{chart-config-sunburst-BPdjbk18.js.map → chart-config-sunburst-Z_gqIY5u.js.map} +1 -1
  71. package/dist/client/chunks/{chart-config-tree-map-Cbsh2fe2.js → chart-config-tree-map-BD-xAeIy.js} +1 -1
  72. package/dist/client/chunks/{chart-config-tree-map-Cbsh2fe2.js.map → chart-config-tree-map-BD-xAeIy.js.map} +1 -1
  73. package/dist/client/chunks/{chart-config-waterfall-DGmuZfQF.js → chart-config-waterfall-CHwVkXZc.js} +1 -1
  74. package/dist/client/chunks/{chart-config-waterfall-DGmuZfQF.js.map → chart-config-waterfall-CHwVkXZc.js.map} +1 -1
  75. package/dist/client/chunks/{chart-data-table-CW_qZDpt.js → chart-data-table-BZ7StNWv.js} +1452 -826
  76. package/dist/client/chunks/chart-data-table-BZ7StNWv.js.map +1 -0
  77. package/dist/client/chunks/{chart-gauge-BLLJqeXo.js → chart-gauge-_Xdgk_qI.js} +1 -1
  78. package/dist/client/chunks/{chart-gauge-BLLJqeXo.js.map → chart-gauge-_Xdgk_qI.js.map} +1 -1
  79. package/dist/client/chunks/{chart-heat-map-f2fM2mDC.js → chart-heat-map-BOMQeUDL.js} +1 -1
  80. package/dist/client/chunks/{chart-heat-map-f2fM2mDC.js.map → chart-heat-map-BOMQeUDL.js.map} +1 -1
  81. package/dist/client/chunks/{chart-kpi-delta-BPexzOe7.js → chart-kpi-delta-C2tdpWki.js} +4 -4
  82. package/dist/client/chunks/{chart-kpi-delta-BPexzOe7.js.map → chart-kpi-delta-C2tdpWki.js.map} +1 -1
  83. package/dist/client/chunks/{chart-kpi-number-BBtGBtZL.js → chart-kpi-number-BUNKM7yg.js} +5 -5
  84. package/dist/client/chunks/{chart-kpi-number-BBtGBtZL.js.map → chart-kpi-number-BUNKM7yg.js.map} +1 -1
  85. package/dist/client/chunks/{chart-kpi-text-BqHhmJEB.js → chart-kpi-text-COF8iN0K.js} +2 -2
  86. package/dist/client/chunks/{chart-kpi-text-BqHhmJEB.js.map → chart-kpi-text-COF8iN0K.js.map} +1 -1
  87. package/dist/client/chunks/{chart-line-CPhQRMZ7.js → chart-line-D3SEwXDS.js} +1 -1
  88. package/dist/client/chunks/{chart-line-CPhQRMZ7.js.map → chart-line-D3SEwXDS.js.map} +1 -1
  89. package/dist/client/chunks/{chart-markdown-B2X4IwLO.js → chart-markdown-DMekYkKz.js} +647 -644
  90. package/dist/client/chunks/chart-markdown-DMekYkKz.js.map +1 -0
  91. package/dist/client/chunks/{chart-measure-profile-CVlqGslU.js → chart-measure-profile-BPhI1Z9s.js} +1 -1
  92. package/dist/client/chunks/{chart-measure-profile-CVlqGslU.js.map → chart-measure-profile-BPhI1Z9s.js.map} +1 -1
  93. package/dist/client/chunks/{chart-pie-DafSc9sE.js → chart-pie-COl3Rmdk.js} +1 -1
  94. package/dist/client/chunks/{chart-pie-DafSc9sE.js.map → chart-pie-COl3Rmdk.js.map} +1 -1
  95. package/dist/client/chunks/{chart-radar-Dz9F5k-B.js → chart-radar-BKZXylBB.js} +1 -1
  96. package/dist/client/chunks/{chart-radar-Dz9F5k-B.js.map → chart-radar-BKZXylBB.js.map} +1 -1
  97. package/dist/client/chunks/{chart-radial-bar-N3MNUL7o.js → chart-radial-bar-CMfC7SPd.js} +1 -1
  98. package/dist/client/chunks/{chart-radial-bar-N3MNUL7o.js.map → chart-radial-bar-CMfC7SPd.js.map} +1 -1
  99. package/dist/client/chunks/{chart-scatter-J2JNi88S.js → chart-scatter-xQMa3dUt.js} +1 -1
  100. package/dist/client/chunks/{chart-scatter-J2JNi88S.js.map → chart-scatter-xQMa3dUt.js.map} +1 -1
  101. package/dist/client/chunks/{chart-sunburst-D1NFQjqk.js → chart-sunburst-BGhJ4fui.js} +1 -1
  102. package/dist/client/chunks/{chart-sunburst-D1NFQjqk.js.map → chart-sunburst-BGhJ4fui.js.map} +1 -1
  103. package/dist/client/chunks/{chart-tree-map-CbYjko2s.js → chart-tree-map-Cn1pmrAw.js} +1 -1
  104. package/dist/client/chunks/{chart-tree-map-CbYjko2s.js.map → chart-tree-map-Cn1pmrAw.js.map} +1 -1
  105. package/dist/client/chunks/{chart-waterfall-Z65TGMUO.js → chart-waterfall-C2nVN4pn.js} +1 -1
  106. package/dist/client/chunks/{chart-waterfall-Z65TGMUO.js.map → chart-waterfall-C2nVN4pn.js.map} +1 -1
  107. package/dist/client/chunks/{charts-core-CJlGzwsW.js → charts-core-Cy3rHADX.js} +1 -1
  108. package/dist/client/chunks/{charts-core-CJlGzwsW.js.map → charts-core-Cy3rHADX.js.map} +1 -1
  109. package/dist/client/chunks/{core-DJrniqct.js → core-BdWfCZ3y.js} +1 -1
  110. package/dist/client/chunks/{core-DJrniqct.js.map → core-BdWfCZ3y.js.map} +1 -1
  111. package/dist/client/chunks/{dist-DDBeV_JI.js → dist-BWPE2m_X.js} +1 -1
  112. package/dist/client/chunks/{dist-DDBeV_JI.js.map → dist-BWPE2m_X.js.map} +1 -1
  113. package/dist/client/chunks/{javascript-BBwTSo6e.js → javascript-O1RIRkZr.js} +1 -1
  114. package/dist/client/chunks/{javascript-BBwTSo6e.js.map → javascript-O1RIRkZr.js.map} +1 -1
  115. package/dist/client/chunks/{json-BpTrLZSh.js → json-C5bX2tt1.js} +1 -1
  116. package/dist/client/chunks/{json-BpTrLZSh.js.map → json-C5bX2tt1.js.map} +1 -1
  117. package/dist/client/chunks/{retention-UEXlSdZ-.js → retention-YhT1Oohi.js} +1 -1
  118. package/dist/client/chunks/{retention-UEXlSdZ-.js.map → retention-YhT1Oohi.js.map} +1 -1
  119. package/dist/client/chunks/{schema-visualization-CwiEtwdu.js → schema-visualization-DVdfx6N8.js} +92 -96
  120. package/dist/client/chunks/schema-visualization-DVdfx6N8.js.map +1 -0
  121. package/dist/client/chunks/{sql-B0chxcEK.js → sql-D2qikO5q.js} +1 -1
  122. package/dist/client/chunks/{sql-B0chxcEK.js.map → sql-D2qikO5q.js.map} +1 -1
  123. package/dist/client/chunks/{syntaxHighlighting-BLl0ch4A.js → syntaxHighlighting-BYYWYmjr.js} +2 -2
  124. package/dist/client/chunks/{syntaxHighlighting-BLl0ch4A.js.map → syntaxHighlighting-BYYWYmjr.js.map} +1 -1
  125. package/dist/client/chunks/{useDebounce-C_wstEud.js → useDebounce-Bel8J05v.js} +12 -12
  126. package/dist/client/chunks/{useDebounce-C_wstEud.js.map → useDebounce-Bel8J05v.js.map} +1 -1
  127. package/dist/client/chunks/{useDirtyStateTracking-CgKZWkel.js → useDirtyStateTracking-KAjwj1Ht.js} +1 -1
  128. package/dist/client/chunks/{useDirtyStateTracking-CgKZWkel.js.map → useDirtyStateTracking-KAjwj1Ht.js.map} +1 -1
  129. package/dist/client/chunks/{useExplainAI-C9ytXRIC.js → useExplainAI-CxdzY2N0.js} +14 -14
  130. package/dist/client/chunks/{useExplainAI-C9ytXRIC.js.map → useExplainAI-CxdzY2N0.js.map} +1 -1
  131. package/dist/client/chunks/{useNotebookLayout-BFZ_33Kb.js → useNotebookLayout-DKkMenhj.js} +1 -1
  132. package/dist/client/chunks/{useNotebookLayout-BFZ_33Kb.js.map → useNotebookLayout-DKkMenhj.js.map} +1 -1
  133. package/dist/client/chunks/{utils-3FNmeZJR.js → utils-CMkS7h9x.js} +2 -2
  134. package/dist/client/chunks/{utils-3FNmeZJR.js.map → utils-CMkS7h9x.js.map} +1 -1
  135. package/dist/client/chunks/{vendor-BPRWulB7.js → vendor-BoWEubRu.js} +40 -40
  136. package/dist/client/chunks/{vendor-BPRWulB7.js.map → vendor-BoWEubRu.js.map} +1 -1
  137. package/dist/client/components.js +3 -3
  138. package/dist/client/hooks.js +5 -5
  139. package/dist/client/icons/registry.d.ts +6 -0
  140. package/dist/client/icons.js +2 -2
  141. package/dist/client/index.d.ts +3 -2
  142. package/dist/client/index.js +39 -41
  143. package/dist/client/index.js.map +1 -1
  144. package/dist/client/providers/CubeProvider.d.ts +4 -1
  145. package/dist/client/providers.js +2 -2
  146. package/dist/client/schema.d.ts +13 -0
  147. package/dist/client/schema.js +2 -0
  148. package/dist/client/styles.css +1 -1
  149. package/dist/client/types.d.ts +2 -1
  150. package/dist/client/utils.js +6 -6
  151. package/dist/client-bundle-stats.html +1 -1
  152. package/package.json +10 -2
  153. package/dist/client/chunks/DashboardEditModal-iGhIvNP6.js.map +0 -1
  154. package/dist/client/chunks/RetentionCombinedChart.config-DprbXd1N.js +0 -56
  155. package/dist/client/chunks/RetentionCombinedChart.config-DprbXd1N.js.map +0 -1
  156. package/dist/client/chunks/RetentionHeatmap.config-cbaNExVy.js +0 -25
  157. package/dist/client/chunks/RetentionHeatmap.config-cbaNExVy.js.map +0 -1
  158. package/dist/client/chunks/analysis-builder-DEGG5NwE.js.map +0 -1
  159. package/dist/client/chunks/analysis-builder-shared-BxHYfTzo.js.map +0 -1
  160. package/dist/client/chunks/chart-data-table-CW_qZDpt.js.map +0 -1
  161. package/dist/client/chunks/chart-markdown-B2X4IwLO.js.map +0 -1
  162. package/dist/client/chunks/charts-loader-gZjOqZwG.js +0 -259
  163. package/dist/client/chunks/charts-loader-gZjOqZwG.js.map +0 -1
  164. package/dist/client/chunks/lazyChartConfigRegistry-BjhxDaSf.js +0 -149
  165. package/dist/client/chunks/lazyChartConfigRegistry-BjhxDaSf.js.map +0 -1
  166. package/dist/client/chunks/schema-visualization-CwiEtwdu.js.map +0 -1
@@ -129,4 +129,4 @@ var s = {
129
129
  //#endregion
130
130
  export { s as a, a as c, l as i, o as l, e as n, i as o, c as r, n as s, t };
131
131
 
132
- //# sourceMappingURL=retention-UEXlSdZ-.js.map
132
+ //# sourceMappingURL=retention-YhT1Oohi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"retention-UEXlSdZ-.js","names":[],"sources":["../../../src/client/types/retention.ts"],"sourcesContent":["/**\n * Retention Analysis Types\n *\n * Types for Retention analysis mode which tracks cohort-based retention over time.\n * Retention analysis measures what percentage of users from each cohort return\n * in subsequent time periods.\n */\n\nimport type { Filter } from '../types'\nimport type { FunnelBindingKey } from './funnel'\n\n// ============================================================================\n// Date Range Types\n// ============================================================================\n\n/**\n * Date range for cohort analysis (REQUIRED)\n * Matches server's RetentionDateRange interface\n */\nexport interface DateRange {\n /** Start date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n start: string\n /** End date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n end: string\n}\n\n/**\n * Preset date range type\n */\nexport type DateRangePreset =\n | 'last_30_days'\n | 'last_3_months'\n | 'last_6_months'\n | 'last_12_months'\n | 'this_year'\n | 'last_year'\n | 'custom'\n\n/**\n * Preset date range options for the UI\n */\nexport const RETENTION_DATE_RANGE_PRESETS: { value: DateRangePreset; label: string }[] = [\n { value: 'last_30_days', label: 'Last 30 days' },\n { value: 'last_3_months', label: 'Last 3 months' },\n { value: 'last_6_months', label: 'Last 6 months' },\n { value: 'last_12_months', label: 'Last 12 months' },\n { value: 'this_year', label: 'This year' },\n { value: 'last_year', label: 'Last year' },\n { value: 'custom', label: 'Custom range' },\n]\n\n/**\n * Default preset for retention date range\n */\nexport const DEFAULT_DATE_RANGE_PRESET: DateRangePreset = 'last_3_months'\n\n/**\n * Calculate date range from a preset value\n * Returns ISO date strings (YYYY-MM-DD)\n */\nexport function getDateRangeFromPreset(preset: DateRangePreset): DateRange {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n\n switch (preset) {\n case 'last_30_days': {\n const start = new Date(today)\n start.setDate(start.getDate() - 30)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_3_months': {\n // Start of 3 months ago to end of last month\n const start = new Date(today.getFullYear(), today.getMonth() - 3, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0) // Last day of previous month\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_6_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 6, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_12_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 12, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'this_year': {\n const start = new Date(today.getFullYear(), 0, 1)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_year': {\n const start = new Date(today.getFullYear() - 1, 0, 1)\n const end = new Date(today.getFullYear() - 1, 11, 31)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'custom':\n default:\n // For custom, return last 3 months as fallback\n return getDateRangeFromPreset('last_3_months')\n }\n}\n\n/**\n * Format a Date object to ISO date string (YYYY-MM-DD)\n */\nfunction formatDateToISO(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\n/**\n * Detect which preset a date range matches, if any\n */\nexport function detectDateRangePreset(range: DateRange): DateRangePreset {\n for (const preset of RETENTION_DATE_RANGE_PRESETS) {\n if (preset.value === 'custom') continue\n const presetRange = getDateRangeFromPreset(preset.value)\n if (presetRange.start === range.start && presetRange.end === range.end) {\n return preset.value\n }\n }\n return 'custom'\n}\n\n// ============================================================================\n// Server Query Format\n// ============================================================================\n\n/**\n * Server retention query format\n * This is the shape sent to the server for execution\n * Wrapped in { retention: {...} } similar to funnel queries\n */\nexport interface ServerRetentionQuery {\n retention: RetentionQueryConfig\n}\n\n/**\n * Retention query configuration\n * Contains all parameters needed for server-side retention analysis\n *\n * Simplified Mixpanel-style format:\n * - Single cube and timestamp dimension\n * - Single cohort (date range defines the cohort, not granularity)\n * - Optional breakdown dimension for segmentation\n */\nexport interface RetentionQueryConfig {\n /**\n * Single timestamp dimension for the analysis.\n * String format (e.g., 'Events.timestamp'),\n * Object format for multi-cube with explicit cube reference.\n */\n timeDimension: string | { cube: string; dimension: string }\n\n /**\n * Binding key - dimension that links users across events.\n * This is typically a user ID or other entity identifier.\n * String for single-cube (e.g., 'Events.userId'),\n * Array for multi-cube with different column names per cube.\n */\n bindingKey: string | { cube: string; dimension: string }[]\n\n /**\n * Date range for cohort analysis (REQUIRED).\n * Users who first performed the cohort action within this range are included.\n */\n dateRange: DateRange\n\n /**\n * Granularity for viewing retention periods.\n * Determines how retention periods are measured (day/week/month).\n */\n granularity: RetentionGranularity\n\n /**\n * Number of periods to calculate (e.g., 12 for 12 weeks).\n * Period 0 is always the cohort entry period.\n */\n periods: number\n\n /**\n * Retention type:\n * - 'classic': User returned exactly in period N (bounded)\n * - 'rolling': User returned in period N or any later period (unbounded)\n */\n retentionType: RetentionType\n\n /**\n * Optional filters on cohort entry events.\n * Applied when identifying which users enter the cohort.\n */\n cohortFilters?: Filter | Filter[]\n\n /**\n * Optional filters on return activity events.\n * Applied when checking for user activity in each period.\n */\n activityFilters?: Filter | Filter[]\n\n /**\n * Optional breakdown dimensions for segmenting the cohort.\n * When provided, retention is calculated per breakdown value combination.\n * e.g., [\"Events.country\"] or [\"Events.country\", \"Events.plan\"]\n */\n breakdownDimensions?: string[]\n}\n\n// ============================================================================\n// Enums and Unions\n// ============================================================================\n\n/**\n * Supported granularity levels for retention analysis\n */\nexport type RetentionGranularity = 'day' | 'week' | 'month'\n\n/**\n * Retention calculation types\n * - classic: User active exactly in period N\n * - rolling: User active in period N or any later period\n */\nexport type RetentionType = 'classic' | 'rolling'\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\n/**\n * Single retention data point returned from server\n * Results are returned as a flat array; client transforms to matrix if needed\n */\nexport interface RetentionResultRow {\n /** Period number (0 = cohort entry, 1 = first retention period, etc.) */\n period: number\n\n /** Number of users in the cohort */\n cohortSize: number\n\n /** Number of users retained in this period */\n retainedUsers: number\n\n /** Retention rate as decimal (0-1), e.g., 0.45 for 45% */\n retentionRate: number\n\n /** Breakdown value when breakdown dimension is specified (e.g., \"US\", \"UK\") */\n breakdownValue?: string | null\n}\n\n/**\n * Retention chart data format for visualization\n * Supports both heatmap and line chart modes\n */\nexport interface RetentionChartData {\n rows: RetentionResultRow[]\n /** Period numbers (0 to periods) */\n periods: number[]\n /** Breakdown values when breakdown dimension is specified */\n breakdownValues?: string[]\n /** Summary statistics */\n summary?: RetentionSummary\n /** Granularity of retention periods (day/week/month) for period label formatting */\n granularity?: RetentionGranularity\n /** Human-readable label extracted from the binding key dimension (e.g., \"userId\" from \"Users.userId\") */\n bindingKeyLabel?: string\n}\n\n/**\n * Summary statistics for retention analysis\n */\nexport interface RetentionSummary {\n /** Total unique users in the cohort */\n totalUsers: number\n /** Average retention rate across all periods for period 1 */\n avgPeriod1Retention: number\n /** Highest retention rate for period 1 */\n maxPeriod1Retention: number\n /** Lowest retention rate for period 1 */\n minPeriod1Retention: number\n /** Number of breakdown segments (1 if no breakdown) */\n segmentCount?: number\n}\n\n// ============================================================================\n// Breakdown Types\n// ============================================================================\n\n/**\n * Breakdown item for retention analysis (single dimension)\n * Follows Mixpanel pattern - one breakdown dimension only\n */\nexport interface RetentionBreakdownItem {\n /** Full dimension name (e.g., \"Events.country\") */\n field: string\n /** Display label for the dimension */\n label?: string\n}\n\n// ============================================================================\n// Slice State (for Zustand store)\n// ============================================================================\n\n/**\n * Retention mode state for the AnalysisBuilder store\n * Simplified Mixpanel-style with single global configuration\n *\n * Key simplifications from previous version:\n * - Single cube for all (no separate cohort/activity cubes)\n * - Single timestamp dimension\n * - Single cohort with breakdown support (no cohort explosion)\n * - Granularity = viewing periods only\n */\nexport interface RetentionSliceState {\n /** Single cube for retention analysis */\n retentionCube: string | null\n\n /** Binding key that identifies entities (reuses funnel binding key type) */\n retentionBindingKey: FunnelBindingKey | null\n\n /** Single timestamp dimension for both cohort entry and activity */\n retentionTimeDimension: string | null\n\n /** Date range for cohort analysis (REQUIRED) */\n retentionDateRange: DateRange\n\n /** Filters that define who enters the cohort */\n retentionCohortFilters: Filter[]\n\n /** Filters that define what counts as a return */\n retentionActivityFilters: Filter[]\n\n /** Optional breakdown dimensions for segmenting the cohort */\n retentionBreakdowns: RetentionBreakdownItem[]\n\n /** Granularity for viewing retention periods (day/week/month) */\n retentionViewGranularity: RetentionGranularity\n\n /** Number of periods to analyze (1-52) */\n retentionPeriods: number\n\n /** Type of retention calculation */\n retentionType: RetentionType\n}\n\n/**\n * Retention slice actions for the store\n */\nexport interface RetentionSliceActions {\n /** Set the single cube for retention analysis */\n setRetentionCube: (cube: string | null) => void\n /** Set the retention binding key */\n setRetentionBindingKey: (key: FunnelBindingKey | null) => void\n /** Set the single timestamp dimension */\n setRetentionTimeDimension: (dim: string | null) => void\n /** Set the date range (REQUIRED) */\n setRetentionDateRange: (range: DateRange) => void\n /** Set all cohort filters at once */\n setRetentionCohortFilters: (filters: Filter[]) => void\n /** Add a cohort filter */\n addRetentionCohortFilter: (filter: Filter) => void\n /** Remove a cohort filter by index */\n removeRetentionCohortFilter: (index: number) => void\n /** Update a cohort filter by index */\n updateRetentionCohortFilter: (index: number, filter: Filter) => void\n /** Set all activity filters at once */\n setRetentionActivityFilters: (filters: Filter[]) => void\n /** Add an activity filter */\n addRetentionActivityFilter: (filter: Filter) => void\n /** Remove an activity filter by index */\n removeRetentionActivityFilter: (index: number) => void\n /** Update an activity filter by index */\n updateRetentionActivityFilter: (index: number, filter: Filter) => void\n /** Set all breakdown dimensions */\n setRetentionBreakdowns: (breakdowns: RetentionBreakdownItem[]) => void\n /** Add a breakdown dimension */\n addRetentionBreakdown: (breakdown: RetentionBreakdownItem) => void\n /** Remove a breakdown dimension by field name */\n removeRetentionBreakdown: (field: string) => void\n /** Set the view granularity */\n setRetentionViewGranularity: (granularity: RetentionGranularity) => void\n /** Set the number of periods */\n setRetentionPeriods: (periods: number) => void\n /** Set the retention type */\n setRetentionType: (type: RetentionType) => void\n /** Check if in retention mode (analysisType === 'retention') */\n isRetentionMode: () => boolean\n /** Check if retention mode is properly configured and ready for execution */\n isRetentionModeEnabled: () => boolean\n /** Build ServerRetentionQuery from retention state */\n buildRetentionQuery: () => ServerRetentionQuery | null\n /** Get validation errors explaining why retention query cannot be built */\n getRetentionValidation: () => { isValid: boolean; errors: string[]; warnings: string[] }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard to check if data is retention chart data\n */\nexport function isRetentionData(data: unknown): data is RetentionChartData {\n if (!data || typeof data !== 'object') return false\n const d = data as Record<string, unknown>\n return (\n Array.isArray(d.rows) &&\n Array.isArray(d.periods)\n )\n}\n\n/**\n * Type guard to detect server retention query format\n * Used to distinguish { retention: {...} } from CubeQuery, etc.\n */\nexport function isServerRetentionQuery(obj: unknown): obj is ServerRetentionQuery {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'retention' in obj &&\n typeof (obj as { retention: unknown }).retention === 'object'\n )\n}\n\n/**\n * Type guard for retention result row\n */\nexport function isRetentionResultRow(row: unknown): row is RetentionResultRow {\n if (!row || typeof row !== 'object') return false\n const r = row as Record<string, unknown>\n return (\n typeof r.cohortPeriod === 'string' &&\n typeof r.period === 'number' &&\n typeof r.cohortSize === 'number' &&\n typeof r.retainedUsers === 'number' &&\n typeof r.retentionRate === 'number'\n )\n}\n\n// ============================================================================\n// Default Values\n// ============================================================================\n\n/**\n * Default retention slice state for store initialization\n */\nexport const defaultRetentionSliceState: RetentionSliceState = {\n retentionCube: null,\n retentionBindingKey: null,\n retentionTimeDimension: null,\n retentionDateRange: getDateRangeFromPreset(DEFAULT_DATE_RANGE_PRESET),\n retentionCohortFilters: [],\n retentionActivityFilters: [],\n retentionBreakdowns: [],\n retentionViewGranularity: 'week',\n retentionPeriods: 12,\n retentionType: 'classic',\n}\n\n/**\n * Minimum and maximum values for retention periods\n */\nexport const RETENTION_MIN_PERIODS = 1\nexport const RETENTION_MAX_PERIODS = 52\n\n/**\n * Available granularity options\n */\nexport const RETENTION_GRANULARITY_OPTIONS: { value: RetentionGranularity; label: string }[] = [\n { value: 'day', label: 'Daily' },\n { value: 'week', label: 'Weekly' },\n { value: 'month', label: 'Monthly' },\n]\n\n/**\n * Available retention type options\n */\nexport const RETENTION_TYPE_OPTIONS: { value: RetentionType; label: string; description: string }[] = [\n {\n value: 'classic',\n label: 'Classic',\n description: 'User was active in exactly period N',\n },\n {\n value: 'rolling',\n label: 'Rolling',\n description: 'User was active in period N or later',\n },\n]\n"],"mappings":"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"}
1
+ {"version":3,"file":"retention-YhT1Oohi.js","names":[],"sources":["../../../src/client/types/retention.ts"],"sourcesContent":["/**\n * Retention Analysis Types\n *\n * Types for Retention analysis mode which tracks cohort-based retention over time.\n * Retention analysis measures what percentage of users from each cohort return\n * in subsequent time periods.\n */\n\nimport type { Filter } from '../types'\nimport type { FunnelBindingKey } from './funnel'\n\n// ============================================================================\n// Date Range Types\n// ============================================================================\n\n/**\n * Date range for cohort analysis (REQUIRED)\n * Matches server's RetentionDateRange interface\n */\nexport interface DateRange {\n /** Start date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n start: string\n /** End date (inclusive), ISO 8601 format (YYYY-MM-DD) */\n end: string\n}\n\n/**\n * Preset date range type\n */\nexport type DateRangePreset =\n | 'last_30_days'\n | 'last_3_months'\n | 'last_6_months'\n | 'last_12_months'\n | 'this_year'\n | 'last_year'\n | 'custom'\n\n/**\n * Preset date range options for the UI\n */\nexport const RETENTION_DATE_RANGE_PRESETS: { value: DateRangePreset; label: string }[] = [\n { value: 'last_30_days', label: 'Last 30 days' },\n { value: 'last_3_months', label: 'Last 3 months' },\n { value: 'last_6_months', label: 'Last 6 months' },\n { value: 'last_12_months', label: 'Last 12 months' },\n { value: 'this_year', label: 'This year' },\n { value: 'last_year', label: 'Last year' },\n { value: 'custom', label: 'Custom range' },\n]\n\n/**\n * Default preset for retention date range\n */\nexport const DEFAULT_DATE_RANGE_PRESET: DateRangePreset = 'last_3_months'\n\n/**\n * Calculate date range from a preset value\n * Returns ISO date strings (YYYY-MM-DD)\n */\nexport function getDateRangeFromPreset(preset: DateRangePreset): DateRange {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n\n switch (preset) {\n case 'last_30_days': {\n const start = new Date(today)\n start.setDate(start.getDate() - 30)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_3_months': {\n // Start of 3 months ago to end of last month\n const start = new Date(today.getFullYear(), today.getMonth() - 3, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0) // Last day of previous month\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_6_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 6, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'last_12_months': {\n const start = new Date(today.getFullYear(), today.getMonth() - 12, 1)\n const end = new Date(today.getFullYear(), today.getMonth(), 0)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'this_year': {\n const start = new Date(today.getFullYear(), 0, 1)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(today),\n }\n }\n case 'last_year': {\n const start = new Date(today.getFullYear() - 1, 0, 1)\n const end = new Date(today.getFullYear() - 1, 11, 31)\n return {\n start: formatDateToISO(start),\n end: formatDateToISO(end),\n }\n }\n case 'custom':\n default:\n // For custom, return last 3 months as fallback\n return getDateRangeFromPreset('last_3_months')\n }\n}\n\n/**\n * Format a Date object to ISO date string (YYYY-MM-DD)\n */\nfunction formatDateToISO(date: Date): string {\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\n/**\n * Detect which preset a date range matches, if any\n */\nexport function detectDateRangePreset(range: DateRange): DateRangePreset {\n for (const preset of RETENTION_DATE_RANGE_PRESETS) {\n if (preset.value === 'custom') continue\n const presetRange = getDateRangeFromPreset(preset.value)\n if (presetRange.start === range.start && presetRange.end === range.end) {\n return preset.value\n }\n }\n return 'custom'\n}\n\n// ============================================================================\n// Server Query Format\n// ============================================================================\n\n/**\n * Server retention query format\n * This is the shape sent to the server for execution\n * Wrapped in { retention: {...} } similar to funnel queries\n */\nexport interface ServerRetentionQuery {\n retention: RetentionQueryConfig\n}\n\n/**\n * Retention query configuration\n * Contains all parameters needed for server-side retention analysis\n *\n * Simplified Mixpanel-style format:\n * - Single cube and timestamp dimension\n * - Single cohort (date range defines the cohort, not granularity)\n * - Optional breakdown dimension for segmentation\n */\nexport interface RetentionQueryConfig {\n /**\n * Single timestamp dimension for the analysis.\n * String format (e.g., 'Events.timestamp'),\n * Object format for multi-cube with explicit cube reference.\n */\n timeDimension: string | { cube: string; dimension: string }\n\n /**\n * Binding key - dimension that links users across events.\n * This is typically a user ID or other entity identifier.\n * String for single-cube (e.g., 'Events.userId'),\n * Array for multi-cube with different column names per cube.\n */\n bindingKey: string | { cube: string; dimension: string }[]\n\n /**\n * Date range for cohort analysis (REQUIRED).\n * Users who first performed the cohort action within this range are included.\n */\n dateRange: DateRange\n\n /**\n * Granularity for viewing retention periods.\n * Determines how retention periods are measured (day/week/month).\n */\n granularity: RetentionGranularity\n\n /**\n * Number of periods to calculate (e.g., 12 for 12 weeks).\n * Period 0 is always the cohort entry period.\n */\n periods: number\n\n /**\n * Retention type:\n * - 'classic': User returned exactly in period N (bounded)\n * - 'rolling': User returned in period N or any later period (unbounded)\n */\n retentionType: RetentionType\n\n /**\n * Optional filters on cohort entry events.\n * Applied when identifying which users enter the cohort.\n */\n cohortFilters?: Filter | Filter[]\n\n /**\n * Optional filters on return activity events.\n * Applied when checking for user activity in each period.\n */\n activityFilters?: Filter | Filter[]\n\n /**\n * Optional breakdown dimensions for segmenting the cohort.\n * When provided, retention is calculated per breakdown value combination.\n * e.g., [\"Events.country\"] or [\"Events.country\", \"Events.plan\"]\n */\n breakdownDimensions?: string[]\n}\n\n// ============================================================================\n// Enums and Unions\n// ============================================================================\n\n/**\n * Supported granularity levels for retention analysis\n */\nexport type RetentionGranularity = 'day' | 'week' | 'month'\n\n/**\n * Retention calculation types\n * - classic: User active exactly in period N\n * - rolling: User active in period N or any later period\n */\nexport type RetentionType = 'classic' | 'rolling'\n\n// ============================================================================\n// Result Types\n// ============================================================================\n\n/**\n * Single retention data point returned from server\n * Results are returned as a flat array; client transforms to matrix if needed\n */\nexport interface RetentionResultRow {\n /** Period number (0 = cohort entry, 1 = first retention period, etc.) */\n period: number\n\n /** Number of users in the cohort */\n cohortSize: number\n\n /** Number of users retained in this period */\n retainedUsers: number\n\n /** Retention rate as decimal (0-1), e.g., 0.45 for 45% */\n retentionRate: number\n\n /** Breakdown value when breakdown dimension is specified (e.g., \"US\", \"UK\") */\n breakdownValue?: string | null\n}\n\n/**\n * Retention chart data format for visualization\n * Supports both heatmap and line chart modes\n */\nexport interface RetentionChartData {\n rows: RetentionResultRow[]\n /** Period numbers (0 to periods) */\n periods: number[]\n /** Breakdown values when breakdown dimension is specified */\n breakdownValues?: string[]\n /** Summary statistics */\n summary?: RetentionSummary\n /** Granularity of retention periods (day/week/month) for period label formatting */\n granularity?: RetentionGranularity\n /** Human-readable label extracted from the binding key dimension (e.g., \"userId\" from \"Users.userId\") */\n bindingKeyLabel?: string\n}\n\n/**\n * Summary statistics for retention analysis\n */\nexport interface RetentionSummary {\n /** Total unique users in the cohort */\n totalUsers: number\n /** Average retention rate across all periods for period 1 */\n avgPeriod1Retention: number\n /** Highest retention rate for period 1 */\n maxPeriod1Retention: number\n /** Lowest retention rate for period 1 */\n minPeriod1Retention: number\n /** Number of breakdown segments (1 if no breakdown) */\n segmentCount?: number\n}\n\n// ============================================================================\n// Breakdown Types\n// ============================================================================\n\n/**\n * Breakdown item for retention analysis (single dimension)\n * Follows Mixpanel pattern - one breakdown dimension only\n */\nexport interface RetentionBreakdownItem {\n /** Full dimension name (e.g., \"Events.country\") */\n field: string\n /** Display label for the dimension */\n label?: string\n}\n\n// ============================================================================\n// Slice State (for Zustand store)\n// ============================================================================\n\n/**\n * Retention mode state for the AnalysisBuilder store\n * Simplified Mixpanel-style with single global configuration\n *\n * Key simplifications from previous version:\n * - Single cube for all (no separate cohort/activity cubes)\n * - Single timestamp dimension\n * - Single cohort with breakdown support (no cohort explosion)\n * - Granularity = viewing periods only\n */\nexport interface RetentionSliceState {\n /** Single cube for retention analysis */\n retentionCube: string | null\n\n /** Binding key that identifies entities (reuses funnel binding key type) */\n retentionBindingKey: FunnelBindingKey | null\n\n /** Single timestamp dimension for both cohort entry and activity */\n retentionTimeDimension: string | null\n\n /** Date range for cohort analysis (REQUIRED) */\n retentionDateRange: DateRange\n\n /** Filters that define who enters the cohort */\n retentionCohortFilters: Filter[]\n\n /** Filters that define what counts as a return */\n retentionActivityFilters: Filter[]\n\n /** Optional breakdown dimensions for segmenting the cohort */\n retentionBreakdowns: RetentionBreakdownItem[]\n\n /** Granularity for viewing retention periods (day/week/month) */\n retentionViewGranularity: RetentionGranularity\n\n /** Number of periods to analyze (1-52) */\n retentionPeriods: number\n\n /** Type of retention calculation */\n retentionType: RetentionType\n}\n\n/**\n * Retention slice actions for the store\n */\nexport interface RetentionSliceActions {\n /** Set the single cube for retention analysis */\n setRetentionCube: (cube: string | null) => void\n /** Set the retention binding key */\n setRetentionBindingKey: (key: FunnelBindingKey | null) => void\n /** Set the single timestamp dimension */\n setRetentionTimeDimension: (dim: string | null) => void\n /** Set the date range (REQUIRED) */\n setRetentionDateRange: (range: DateRange) => void\n /** Set all cohort filters at once */\n setRetentionCohortFilters: (filters: Filter[]) => void\n /** Add a cohort filter */\n addRetentionCohortFilter: (filter: Filter) => void\n /** Remove a cohort filter by index */\n removeRetentionCohortFilter: (index: number) => void\n /** Update a cohort filter by index */\n updateRetentionCohortFilter: (index: number, filter: Filter) => void\n /** Set all activity filters at once */\n setRetentionActivityFilters: (filters: Filter[]) => void\n /** Add an activity filter */\n addRetentionActivityFilter: (filter: Filter) => void\n /** Remove an activity filter by index */\n removeRetentionActivityFilter: (index: number) => void\n /** Update an activity filter by index */\n updateRetentionActivityFilter: (index: number, filter: Filter) => void\n /** Set all breakdown dimensions */\n setRetentionBreakdowns: (breakdowns: RetentionBreakdownItem[]) => void\n /** Add a breakdown dimension */\n addRetentionBreakdown: (breakdown: RetentionBreakdownItem) => void\n /** Remove a breakdown dimension by field name */\n removeRetentionBreakdown: (field: string) => void\n /** Set the view granularity */\n setRetentionViewGranularity: (granularity: RetentionGranularity) => void\n /** Set the number of periods */\n setRetentionPeriods: (periods: number) => void\n /** Set the retention type */\n setRetentionType: (type: RetentionType) => void\n /** Check if in retention mode (analysisType === 'retention') */\n isRetentionMode: () => boolean\n /** Check if retention mode is properly configured and ready for execution */\n isRetentionModeEnabled: () => boolean\n /** Build ServerRetentionQuery from retention state */\n buildRetentionQuery: () => ServerRetentionQuery | null\n /** Get validation errors explaining why retention query cannot be built */\n getRetentionValidation: () => { isValid: boolean; errors: string[]; warnings: string[] }\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Type guard to check if data is retention chart data\n */\nexport function isRetentionData(data: unknown): data is RetentionChartData {\n if (!data || typeof data !== 'object') return false\n const d = data as Record<string, unknown>\n return (\n Array.isArray(d.rows) &&\n Array.isArray(d.periods)\n )\n}\n\n/**\n * Type guard to detect server retention query format\n * Used to distinguish { retention: {...} } from CubeQuery, etc.\n */\nexport function isServerRetentionQuery(obj: unknown): obj is ServerRetentionQuery {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n 'retention' in obj &&\n typeof (obj as { retention: unknown }).retention === 'object'\n )\n}\n\n/**\n * Type guard for retention result row\n */\nexport function isRetentionResultRow(row: unknown): row is RetentionResultRow {\n if (!row || typeof row !== 'object') return false\n const r = row as Record<string, unknown>\n return (\n typeof r.cohortPeriod === 'string' &&\n typeof r.period === 'number' &&\n typeof r.cohortSize === 'number' &&\n typeof r.retainedUsers === 'number' &&\n typeof r.retentionRate === 'number'\n )\n}\n\n// ============================================================================\n// Default Values\n// ============================================================================\n\n/**\n * Default retention slice state for store initialization\n */\nexport const defaultRetentionSliceState: RetentionSliceState = {\n retentionCube: null,\n retentionBindingKey: null,\n retentionTimeDimension: null,\n retentionDateRange: getDateRangeFromPreset(DEFAULT_DATE_RANGE_PRESET),\n retentionCohortFilters: [],\n retentionActivityFilters: [],\n retentionBreakdowns: [],\n retentionViewGranularity: 'week',\n retentionPeriods: 12,\n retentionType: 'classic',\n}\n\n/**\n * Minimum and maximum values for retention periods\n */\nexport const RETENTION_MIN_PERIODS = 1\nexport const RETENTION_MAX_PERIODS = 52\n\n/**\n * Available granularity options\n */\nexport const RETENTION_GRANULARITY_OPTIONS: { value: RetentionGranularity; label: string }[] = [\n { value: 'day', label: 'Daily' },\n { value: 'week', label: 'Weekly' },\n { value: 'month', label: 'Monthly' },\n]\n\n/**\n * Available retention type options\n */\nexport const RETENTION_TYPE_OPTIONS: { value: RetentionType; label: string; description: string }[] = [\n {\n value: 'classic',\n label: 'Classic',\n description: 'User was active in exactly period N',\n },\n {\n value: 'rolling',\n label: 'Rolling',\n description: 'User was active in period N or later',\n },\n]\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { n as e } from "./rolldown-runtime-lc2dmIiU.js";
2
- import { c as t, d as n } from "./chart-data-table-CW_qZDpt.js";
2
+ import { A as t, c as n } from "./chart-data-table-BZ7StNWv.js";
3
3
  import { Suspense as r, createContext as i, lazy as a, useCallback as o, useContext as s, useEffect as c, useMemo as l, useRef as u, useState as d } from "react";
4
4
  import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
5
5
  //#region src/client/components/SchemaVisualization/xyflowContext.tsx
@@ -11,8 +11,8 @@ function _() {
11
11
  }
12
12
  //#endregion
13
13
  //#region src/client/components/SchemaVisualization/SchemaVisualizationLazy.tsx
14
- var v = !1;
15
- function y(e) {
14
+ var v = /* @__PURE__ */ e({ SchemaVisualizationLazy: () => C }), y = !1;
15
+ function b(e) {
16
16
  return /* @__PURE__ */ p("div", {
17
17
  className: "dc:flex dc:items-center dc:justify-center dc:h-full dc:p-8",
18
18
  children: /* @__PURE__ */ m("div", {
@@ -38,7 +38,7 @@ function y(e) {
38
38
  })
39
39
  });
40
40
  }
41
- function b() {
41
+ function x() {
42
42
  return /* @__PURE__ */ p("div", {
43
43
  className: "dc:flex dc:items-center dc:justify-center dc:h-full",
44
44
  children: /* @__PURE__ */ m("div", {
@@ -50,36 +50,36 @@ function b() {
50
50
  })
51
51
  });
52
52
  }
53
- var x = a(async () => ({ default: (await Promise.resolve().then(() => R)).SchemaVisualization }));
54
- function S(e) {
55
- let [t, n] = d(null), [i, a] = d(v);
53
+ var S = a(async () => ({ default: (await Promise.resolve().then(() => R)).SchemaVisualization }));
54
+ function C(e) {
55
+ let [t, n] = d(null), [i, a] = d(y);
56
56
  return c(() => {
57
- if (v) return;
57
+ if (y) return;
58
58
  let e = !1;
59
- return import(["@xyflow", "react"].join("/")).then((t) => {
59
+ return import("@xyflow/react").then((t) => {
60
60
  e || n(t);
61
61
  }).catch(() => {
62
- v = !0, e || a(!0);
62
+ y = !0, e || a(!0);
63
63
  }), () => {
64
64
  e = !0;
65
65
  };
66
- }, []), i ? /* @__PURE__ */ p(y, { ...e }) : t ? /* @__PURE__ */ p(g, {
66
+ }, []), i ? /* @__PURE__ */ p(b, { ...e }) : t ? /* @__PURE__ */ p(g, {
67
67
  value: t,
68
68
  children: /* @__PURE__ */ p(r, {
69
- fallback: /* @__PURE__ */ p(b, {}),
70
- children: /* @__PURE__ */ p(x, { ...e })
69
+ fallback: /* @__PURE__ */ p(x, {}),
70
+ children: /* @__PURE__ */ p(S, { ...e })
71
71
  })
72
- }) : /* @__PURE__ */ p(b, {});
72
+ }) : /* @__PURE__ */ p(x, {});
73
73
  }
74
74
  //#endregion
75
75
  //#region src/client/components/SchemaVisualization/CubeNode.tsx
76
- function C({ data: e }) {
77
- let { Handle: t, Position: r } = _(), { cube: i, onFieldClick: a, onCubeClick: o, isHighlighted: s, highlightedFields: c, searchTerm: l, selectedField: u } = e, d = (e, t, n) => {
76
+ function w({ data: e }) {
77
+ let { Handle: n, Position: r } = _(), { cube: i, onFieldClick: a, onCubeClick: o, isHighlighted: s, highlightedFields: c, searchTerm: l, selectedField: u } = e, d = (e, t, n) => {
78
78
  a && a(i.name, t, n, {
79
79
  x: e.clientX,
80
80
  y: e.clientY
81
81
  });
82
- }, f = n("info"), h = (e) => {
82
+ }, f = t("info"), h = (e) => {
83
83
  e.stopPropagation(), o && o(i.name, {
84
84
  x: e.clientX,
85
85
  y: e.clientY
@@ -233,28 +233,28 @@ function C({ data: e }) {
233
233
  })
234
234
  })]
235
235
  }),
236
- /* @__PURE__ */ p(t, {
236
+ /* @__PURE__ */ p(n, {
237
237
  type: "source",
238
238
  position: r.Right,
239
239
  id: "right",
240
240
  className: "dc:opacity-0",
241
241
  isConnectable: !1
242
242
  }),
243
- /* @__PURE__ */ p(t, {
243
+ /* @__PURE__ */ p(n, {
244
244
  type: "target",
245
245
  position: r.Left,
246
246
  id: "left",
247
247
  className: "dc:opacity-0",
248
248
  isConnectable: !1
249
249
  }),
250
- /* @__PURE__ */ p(t, {
250
+ /* @__PURE__ */ p(n, {
251
251
  type: "source",
252
252
  position: r.Bottom,
253
253
  id: "bottom",
254
254
  className: "dc:opacity-0",
255
255
  isConnectable: !1
256
256
  }),
257
- /* @__PURE__ */ p(t, {
257
+ /* @__PURE__ */ p(n, {
258
258
  type: "target",
259
259
  position: r.Top,
260
260
  id: "top",
@@ -266,7 +266,7 @@ function C({ data: e }) {
266
266
  }
267
267
  //#endregion
268
268
  //#region src/client/components/SchemaVisualization/RelationshipEdge.tsx
269
- function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourcePosition: i, targetPosition: a, style: o = {}, data: s, markerEnd: c }) {
269
+ function T({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourcePosition: i, targetPosition: a, style: o = {}, data: s, markerEnd: c }) {
270
270
  let { getBezierPath: l, BaseEdge: u, EdgeLabelRenderer: d } = _(), [h, g, v] = l({
271
271
  sourceX: e,
272
272
  sourceY: t,
@@ -337,7 +337,7 @@ function w({ sourceX: e, sourceY: t, targetX: n, targetY: r, sourcePosition: i,
337
337
  }
338
338
  //#endregion
339
339
  //#region src/client/components/SchemaVisualization/FieldDetailPanel.tsx
340
- function T({ label: e, children: t }) {
340
+ function E({ label: e, children: t }) {
341
341
  return /* @__PURE__ */ m("div", {
342
342
  className: "dc:flex dc:items-start dc:gap-2 dc:text-xs",
343
343
  children: [/* @__PURE__ */ p("span", {
@@ -349,7 +349,7 @@ function T({ label: e, children: t }) {
349
349
  })]
350
350
  });
351
351
  }
352
- function E({ type: e, color: t }) {
352
+ function D({ type: e, color: t }) {
353
353
  return /* @__PURE__ */ p("span", {
354
354
  className: "dc:inline-flex dc:items-center dc:px-1.5 dc:py-0.5 dc:rounded dc:text-[10px] dc:font-medium dc:uppercase",
355
355
  style: {
@@ -359,17 +359,17 @@ function E({ type: e, color: t }) {
359
359
  children: e
360
360
  });
361
361
  }
362
- function D({ measure: e, cube: t }) {
362
+ function O({ measure: e, cube: t }) {
363
363
  return /* @__PURE__ */ m("div", {
364
364
  className: "dc:flex dc:flex-col dc:gap-2",
365
365
  children: [
366
- /* @__PURE__ */ p(T, {
366
+ /* @__PURE__ */ p(E, {
367
367
  label: "Cube",
368
368
  children: t.title || t.name
369
369
  }),
370
- /* @__PURE__ */ p(T, {
370
+ /* @__PURE__ */ p(E, {
371
371
  label: "Type",
372
- children: /* @__PURE__ */ p(E, {
372
+ children: /* @__PURE__ */ p(D, {
373
373
  type: e.type,
374
374
  color: {
375
375
  count: "#f59e0b",
@@ -384,11 +384,11 @@ function D({ measure: e, cube: t }) {
384
384
  }[e.type] || "#6b7280"
385
385
  })
386
386
  }),
387
- e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(T, {
387
+ e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(E, {
388
388
  label: "Title",
389
389
  children: e.title
390
390
  }),
391
- e.drillMembers && e.drillMembers.length > 0 && /* @__PURE__ */ p(T, {
391
+ e.drillMembers && e.drillMembers.length > 0 && /* @__PURE__ */ p(E, {
392
392
  label: "Drill into",
393
393
  children: /* @__PURE__ */ p("div", {
394
394
  className: "dc:flex dc:flex-wrap dc:gap-1",
@@ -401,27 +401,27 @@ function D({ measure: e, cube: t }) {
401
401
  ]
402
402
  });
403
403
  }
404
- function O({ dimension: e, cube: t }) {
404
+ function k({ dimension: e, cube: t }) {
405
405
  let n = e.type === "time" ? "#3b82f6" : "#10b981", r = t.hierarchies?.filter((n) => n.levels.some((n) => n === e.name || n === `${t.name}.${e.name.split(".")[1]}`)) || [];
406
406
  return /* @__PURE__ */ m("div", {
407
407
  className: "dc:flex dc:flex-col dc:gap-2",
408
408
  children: [
409
- /* @__PURE__ */ p(T, {
409
+ /* @__PURE__ */ p(E, {
410
410
  label: "Cube",
411
411
  children: t.title || t.name
412
412
  }),
413
- /* @__PURE__ */ p(T, {
413
+ /* @__PURE__ */ p(E, {
414
414
  label: "Type",
415
- children: /* @__PURE__ */ p(E, {
415
+ children: /* @__PURE__ */ p(D, {
416
416
  type: e.type,
417
417
  color: n
418
418
  })
419
419
  }),
420
- e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(T, {
420
+ e.title && e.title !== e.shortTitle && /* @__PURE__ */ p(E, {
421
421
  label: "Title",
422
422
  children: e.title
423
423
  }),
424
- e.type === "time" && e.granularities && e.granularities.length > 0 && /* @__PURE__ */ p(T, {
424
+ e.type === "time" && e.granularities && e.granularities.length > 0 && /* @__PURE__ */ p(E, {
425
425
  label: "Granularity",
426
426
  children: /* @__PURE__ */ p("div", {
427
427
  className: "dc:flex dc:flex-wrap dc:gap-1",
@@ -431,7 +431,7 @@ function O({ dimension: e, cube: t }) {
431
431
  }, e))
432
432
  })
433
433
  }),
434
- r.length > 0 && /* @__PURE__ */ p(T, {
434
+ r.length > 0 && /* @__PURE__ */ p(E, {
435
435
  label: "Hierarchy",
436
436
  children: r.map((e) => /* @__PURE__ */ m("div", {
437
437
  className: "dc:text-[10px]",
@@ -451,7 +451,7 @@ function O({ dimension: e, cube: t }) {
451
451
  ]
452
452
  });
453
453
  }
454
- function k({ cube: e }) {
454
+ function ee({ cube: e }) {
455
455
  let t = {
456
456
  belongsTo: "#10b981",
457
457
  hasOne: "#3b82f6",
@@ -461,11 +461,11 @@ function k({ cube: e }) {
461
461
  return /* @__PURE__ */ m("div", {
462
462
  className: "dc:flex dc:flex-col dc:gap-2",
463
463
  children: [
464
- e.description && /* @__PURE__ */ p(T, {
464
+ e.description && /* @__PURE__ */ p(E, {
465
465
  label: "Description",
466
466
  children: e.description
467
467
  }),
468
- /* @__PURE__ */ m(T, {
468
+ /* @__PURE__ */ m(E, {
469
469
  label: "Measures",
470
470
  children: [/* @__PURE__ */ p("span", {
471
471
  className: "dc:font-mono",
@@ -479,7 +479,7 @@ function k({ cube: e }) {
479
479
  ]
480
480
  })]
481
481
  }),
482
- /* @__PURE__ */ m(T, {
482
+ /* @__PURE__ */ m(E, {
483
483
  label: "Dimensions",
484
484
  children: [/* @__PURE__ */ p("span", {
485
485
  className: "dc:font-mono",
@@ -493,13 +493,13 @@ function k({ cube: e }) {
493
493
  ]
494
494
  })]
495
495
  }),
496
- e.relationships && e.relationships.length > 0 && /* @__PURE__ */ p(T, {
496
+ e.relationships && e.relationships.length > 0 && /* @__PURE__ */ p(E, {
497
497
  label: "Joins",
498
498
  children: /* @__PURE__ */ p("div", {
499
499
  className: "dc:flex dc:flex-col dc:gap-1",
500
500
  children: e.relationships.map((e, n) => /* @__PURE__ */ m("div", {
501
501
  className: "dc:flex dc:items-center dc:gap-1.5 dc:text-[10px]",
502
- children: [/* @__PURE__ */ p(E, {
502
+ children: [/* @__PURE__ */ p(D, {
503
503
  type: e.relationship,
504
504
  color: t[e.relationship] || "#6b7280"
505
505
  }), /* @__PURE__ */ p("span", {
@@ -509,7 +509,7 @@ function k({ cube: e }) {
509
509
  }, n))
510
510
  })
511
511
  }),
512
- e.hierarchies && e.hierarchies.length > 0 && /* @__PURE__ */ p(T, {
512
+ e.hierarchies && e.hierarchies.length > 0 && /* @__PURE__ */ p(E, {
513
513
  label: "Hierarchies",
514
514
  children: /* @__PURE__ */ p("div", {
515
515
  className: "dc:flex dc:flex-col dc:gap-1",
@@ -529,7 +529,7 @@ function k({ cube: e }) {
529
529
  }, e.name))
530
530
  })
531
531
  }),
532
- e.meta?.eventStream && /* @__PURE__ */ p(T, {
532
+ e.meta?.eventStream && /* @__PURE__ */ p(E, {
533
533
  label: "Event Stream",
534
534
  children: /* @__PURE__ */ m("div", {
535
535
  className: "dc:text-[10px]",
@@ -556,22 +556,22 @@ function k({ cube: e }) {
556
556
  ]
557
557
  });
558
558
  }
559
- function ee({ selection: e, meta: t, onClose: r }) {
560
- let i = n("close"), a = t.cubes.find((t) => t.name === e.cubeName);
559
+ function te({ selection: e, meta: n, onClose: r }) {
560
+ let i = t("close"), a = n.cubes.find((t) => t.name === e.cubeName);
561
561
  if (!a) return null;
562
562
  let o, s, c, l;
563
- if (e.fieldType === "cube" || !e.fieldName) o = a.title || a.name, s = "var(--dc-accent)", c = "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(k, { cube: a });
563
+ if (e.fieldType === "cube" || !e.fieldName) o = a.title || a.name, s = "var(--dc-accent)", c = "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(ee, { cube: a });
564
564
  else if (e.fieldType === "measure") {
565
565
  let t = a.measures.find((t) => (t.name.split(".")[1] || t.name) === e.fieldName || t.name === e.fieldName);
566
566
  if (!t) return null;
567
- o = t.shortTitle || t.title || e.fieldName, s = "var(--dc-warning)", c = "color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(D, {
567
+ o = t.shortTitle || t.title || e.fieldName, s = "var(--dc-warning)", c = "color-mix(in srgb, var(--dc-warning) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(O, {
568
568
  measure: t,
569
569
  cube: a
570
570
  });
571
571
  } else {
572
572
  let t = a.dimensions.find((t) => (t.name.split(".")[1] || t.name) === e.fieldName || t.name === e.fieldName);
573
573
  if (!t) return null;
574
- o = t.shortTitle || t.title || e.fieldName, s = t.type === "time" ? "var(--dc-accent)" : "var(--dc-success)", c = t.type === "time" ? "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))" : "color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(O, {
574
+ o = t.shortTitle || t.title || e.fieldName, s = t.type === "time" ? "var(--dc-accent)" : "var(--dc-success)", c = t.type === "time" ? "color-mix(in srgb, var(--dc-accent) 10%, var(--dc-surface))" : "color-mix(in srgb, var(--dc-success) 10%, var(--dc-surface))", l = /* @__PURE__ */ p(k, {
575
575
  dimension: t,
576
576
  cube: a
577
577
  });
@@ -604,7 +604,7 @@ function ee({ selection: e, meta: t, onClose: r }) {
604
604
  }
605
605
  //#endregion
606
606
  //#region src/client/components/SchemaVisualization/useERDLayout.ts
607
- var te = {
607
+ var ne = {
608
608
  direction: "LR",
609
609
  nodeWidth: 340,
610
610
  nodeSep: 150,
@@ -632,11 +632,7 @@ function M(e) {
632
632
  }
633
633
  var N = null, P = null;
634
634
  function F() {
635
- return P || (P = import([
636
- "elkjs",
637
- "lib",
638
- "elk.bundled.js"
639
- ].join("/")).then((e) => (N = new (e.default || e)(), N)).catch(() => null), P);
635
+ return P || (P = import("elkjs/lib/elk.bundled.js").then((e) => (N = new (e.default || e)(), N)).catch(() => null), P);
640
636
  }
641
637
  async function I(e, t, n) {
642
638
  if (await F(), !N) return {
@@ -715,9 +711,9 @@ function L(e, t) {
715
711
  };
716
712
  });
717
713
  }
718
- function ne(e, t, n = {}) {
714
+ function re(e, t, n = {}) {
719
715
  let r = l(() => ({
720
- ...te,
716
+ ...ne,
721
717
  ...n
722
718
  }), [
723
719
  n.direction,
@@ -756,8 +752,8 @@ function ne(e, t, n = {}) {
756
752
  var R = /* @__PURE__ */ e({
757
753
  SchemaVisualization: () => B,
758
754
  default: () => B
759
- }), re = { cubeNode: C }, ie = { relationshipEdge: w };
760
- function ae({ token: e }) {
755
+ }), ie = { cubeNode: w }, ae = { relationshipEdge: T };
756
+ function oe({ token: e }) {
761
757
  let { useNodesInitialized: t, useReactFlow: n } = _(), r = t(), { fitView: i } = n(), a = u(0);
762
758
  return c(() => {
763
759
  e === 0 || e === a.current || r && (a.current = e, i({ padding: .1 }));
@@ -768,7 +764,7 @@ function ae({ token: e }) {
768
764
  ]), null;
769
765
  }
770
766
  var z = [];
771
- function oe(e) {
767
+ function se(e) {
772
768
  switch (e) {
773
769
  case "belongsTo": return "#10b981";
774
770
  case "hasOne": return "#3b82f6";
@@ -778,13 +774,13 @@ function oe(e) {
778
774
  }
779
775
  }
780
776
  function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlightedFields: a, searchTerm: s, height: f = "100%" }) {
781
- let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } = t(), w = i || z, T = a || z, [E, D] = d(null), [O, k] = d(s || ""), [te, A] = d(0), [j, M] = d(null), [N, P] = d(null), F = u(null), I = !r, [L, R] = d({}), [B, se] = d(!1), ce = n("search"), le = n("close"), V = s === void 0 ? O : s;
777
+ let { ReactFlow: h, Controls: g, MiniMap: v, Background: y, applyNodeChanges: b } = _(), { meta: x, metaLoading: S, metaError: C } = n(), w = i || z, T = a || z, [E, D] = d(null), [O, k] = d(s || ""), [ee, ne] = d(0), [A, j] = d(null), [M, N] = d(null), P = u(null), F = !r, [I, L] = d({}), [R, B] = d(!1), ce = t("search"), le = t("close"), V = s === void 0 ? O : s;
782
778
  c(() => {
783
779
  try {
784
780
  let e = localStorage.getItem("drizzle-cube-erd-node-positions");
785
- e && R(JSON.parse(e));
781
+ e && L(JSON.parse(e));
786
782
  } catch {}
787
- se(!0);
783
+ B(!0);
788
784
  }, []);
789
785
  let { structuralNodes: H, structuralEdges: U } = l(() => {
790
786
  if (!x) return {
@@ -813,7 +809,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
813
809
  },
814
810
  animated: !1,
815
811
  style: {
816
- stroke: oe(n.relationship),
812
+ stroke: se(n.relationship),
817
813
  strokeWidth: 2
818
814
  }
819
815
  });
@@ -822,13 +818,13 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
822
818
  structuralNodes: e,
823
819
  structuralEdges: t
824
820
  };
825
- }, [x]), W = te > 0 || B && Object.keys(L).length === 0, { nodes: G, edges: K, phase: ue } = ne(W ? H : [], W ? U : [], {
821
+ }, [x]), W = ee > 0 || R && Object.keys(I).length === 0, { nodes: G, edges: K, phase: ue } = re(W ? H : [], W ? U : [], {
826
822
  direction: "LR",
827
823
  nodeWidth: 340,
828
824
  nodeSep: 150,
829
825
  rankSep: 350
830
826
  }), q = o((e, t) => {
831
- let n = F.current?.getBoundingClientRect();
827
+ let n = P.current?.getBoundingClientRect();
832
828
  if (!n) return {
833
829
  x: e,
834
830
  y: t
@@ -839,48 +835,48 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
839
835
  y: i
840
836
  };
841
837
  }, []), de = o((e, t, n, r) => {
842
- M((i) => i && i.cubeName === e && i.fieldName === t ? (P(null), null) : (r && P(q(r.x, r.y)), {
838
+ j((i) => i && i.cubeName === e && i.fieldName === t ? (N(null), null) : (r && N(q(r.x, r.y)), {
843
839
  cubeName: e,
844
840
  fieldName: t,
845
841
  fieldType: n
846
842
  }));
847
843
  }, [q]), fe = o((e, t) => {
848
- M((n) => n && n.cubeName === e && n.fieldName === null ? (P(null), null) : (t && P(q(t.x, t.y)), {
844
+ j((n) => n && n.cubeName === e && n.fieldName === null ? (N(null), null) : (t && N(q(t.x, t.y)), {
849
845
  cubeName: e,
850
846
  fieldName: null,
851
847
  fieldType: "cube"
852
848
  }));
853
- }, [q]), pe = I ? de : r, me = I ? fe : void 0, J = o((e) => ({
849
+ }, [q]), pe = F ? de : r, me = F ? fe : void 0, J = o((e) => ({
854
850
  cube: e,
855
851
  onFieldClick: pe,
856
852
  onCubeClick: me,
857
853
  isHighlighted: w.includes(e.name),
858
854
  highlightedFields: T,
859
855
  searchTerm: V,
860
- selectedField: I ? j : null
856
+ selectedField: F ? A : null
861
857
  }), [
862
858
  pe,
863
859
  me,
864
860
  w,
865
861
  T,
866
862
  V,
867
- I,
868
- j
869
- ]), Y = !W || ue === "ready", X = l(() => !x || !Y || !B ? [] : W && G.length > 0 ? G.map((e) => ({
863
+ F,
864
+ A
865
+ ]), Y = !W || ue === "ready", X = l(() => !x || !Y || !R ? [] : W && G.length > 0 ? G.map((e) => ({
870
866
  ...e,
871
867
  data: J(e.data?.cube || x.cubes.find((t) => t.name === e.id))
872
868
  })) : H.map((e) => ({
873
869
  ...e,
874
- position: L[e.id] || e.position,
870
+ position: I[e.id] || e.position,
875
871
  data: J(e.data?.cube)
876
872
  })), [
877
873
  x,
878
874
  Y,
879
- B,
875
+ R,
880
876
  W,
881
877
  G,
882
878
  H,
883
- L,
879
+ I,
884
880
  J
885
881
  ]), he = l(() => !x || !Y ? [] : W && K.length > 0 ? K : U, [
886
882
  x,
@@ -898,7 +894,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
898
894
  }, [X, he]);
899
895
  let be = u("");
900
896
  c(() => {
901
- let e = j ? `${j.cubeName}.${j.fieldName}` : "", t = `${w.join(",")}|${T.join(",")}|${V}|${String(r)}|${e}`;
897
+ let e = A ? `${A.cubeName}.${A.fieldName}` : "", t = `${w.join(",")}|${T.join(",")}|${V}|${String(r)}|${e}`;
902
898
  t !== be.current && (be.current = t, !(Z.length === 0 || !x) && Q((e) => e.map((e) => {
903
899
  let t = x.cubes.find((t) => t.name === e.id);
904
900
  return t ? {
@@ -911,7 +907,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
911
907
  T,
912
908
  V,
913
909
  r,
914
- j,
910
+ A,
915
911
  Z.length,
916
912
  x,
917
913
  J
@@ -925,7 +921,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
925
921
  try {
926
922
  localStorage.setItem("drizzle-cube-erd-node-positions", JSON.stringify(t));
927
923
  } catch {}
928
- return R(t), e;
924
+ return L(t), e;
929
925
  });
930
926
  }, []), Se = o((e) => {}, []), Ce = o((e) => {
931
927
  e.preventDefault(), e.stopPropagation(), D({
@@ -933,13 +929,13 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
933
929
  y: e.clientY
934
930
  });
935
931
  }, []), we = o(() => {
936
- E && D(null), j && (M(null), P(null));
937
- }, [E, j]), Te = o(() => {
938
- R({}), $.current = "";
932
+ E && D(null), A && (j(null), N(null));
933
+ }, [E, A]), Te = o(() => {
934
+ L({}), $.current = "";
939
935
  try {
940
936
  localStorage.removeItem("drizzle-cube-erd-node-positions");
941
937
  } catch {}
942
- A((e) => e + 1), D(null);
938
+ ne((e) => e + 1), D(null);
943
939
  }, []);
944
940
  return S ? /* @__PURE__ */ p("div", {
945
941
  className: `dc:flex dc:items-center dc:justify-center dc:h-96 ${e}`,
@@ -1000,7 +996,7 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1000
996
  ]
1001
997
  }),
1002
998
  /* @__PURE__ */ m("div", {
1003
- ref: F,
999
+ ref: P,
1004
1000
  className: "dc:relative dc:flex-1 dc:min-h-0",
1005
1001
  children: [/* @__PURE__ */ p("div", {
1006
1002
  style: {
@@ -1012,8 +1008,8 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1012
1008
  edges: ge,
1013
1009
  onNodesChange: xe,
1014
1010
  onEdgesChange: Se,
1015
- nodeTypes: re,
1016
- edgeTypes: ie,
1011
+ nodeTypes: ie,
1012
+ edgeTypes: ae,
1017
1013
  connectionMode: "loose",
1018
1014
  minZoom: .1,
1019
1015
  maxZoom: 2,
@@ -1031,20 +1027,20 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1031
1027
  gap: 12,
1032
1028
  size: 1
1033
1029
  }),
1034
- /* @__PURE__ */ p(ae, { token: ve })
1030
+ /* @__PURE__ */ p(oe, { token: ve })
1035
1031
  ]
1036
1032
  })
1037
- }), I && j && N && x && /* @__PURE__ */ p("div", {
1033
+ }), F && A && M && x && /* @__PURE__ */ p("div", {
1038
1034
  className: "dc:absolute dc:z-20",
1039
1035
  style: {
1040
- left: N.x,
1041
- top: N.y
1036
+ left: M.x,
1037
+ top: M.y
1042
1038
  },
1043
- children: /* @__PURE__ */ p(ee, {
1044
- selection: j,
1039
+ children: /* @__PURE__ */ p(te, {
1040
+ selection: A,
1045
1041
  meta: x,
1046
1042
  onClose: () => {
1047
- M(null), P(null);
1043
+ j(null), N(null);
1048
1044
  }
1049
1045
  })
1050
1046
  })]
@@ -1074,6 +1070,6 @@ function B({ className: e = "", onFieldClick: r, highlightedCubes: i, highlighte
1074
1070
  });
1075
1071
  }
1076
1072
  //#endregion
1077
- export { S as n, R as t };
1073
+ export { C as n, v as r, R as t };
1078
1074
 
1079
- //# sourceMappingURL=schema-visualization-CwiEtwdu.js.map
1075
+ //# sourceMappingURL=schema-visualization-DVdfx6N8.js.map