@almadar/ui 4.26.0 → 4.27.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.
@@ -41,6 +41,7 @@ var postprocessing = require('@react-three/postprocessing');
41
41
  var patterns = require('@almadar/patterns');
42
42
  var ELK = require('elkjs/lib/elk.bundled.js');
43
43
  var react = require('@xyflow/react');
44
+ var OrbitalServerRuntime = require('@almadar/runtime/OrbitalServerRuntime');
44
45
  var runtime = require('@almadar/runtime');
45
46
 
46
47
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -181,7 +182,7 @@ var init_types = __esm({
181
182
  }
182
183
  });
183
184
 
184
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
185
+ // node_modules/clsx/dist/clsx.mjs
185
186
  function r(e) {
186
187
  var t, f, n = "";
187
188
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -196,11 +197,11 @@ function clsx() {
196
197
  return n;
197
198
  }
198
199
  var init_clsx = __esm({
199
- "node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
200
+ "node_modules/clsx/dist/clsx.mjs"() {
200
201
  }
201
202
  });
202
203
 
203
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
204
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
204
205
  function twJoin() {
205
206
  let index = 0;
206
207
  let argument;
@@ -244,7 +245,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
244
245
  }
245
246
  var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
246
247
  var init_bundle_mjs = __esm({
247
- "node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
248
+ "node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
248
249
  CLASS_PART_SEPARATOR = "-";
249
250
  createClassGroupUtils = (config) => {
250
251
  const classMap = createClassMap(config);
@@ -10212,13 +10213,13 @@ var init_MapView = __esm({
10212
10213
  shadowSize: [41, 41]
10213
10214
  });
10214
10215
  L.Marker.prototype.options.icon = defaultIcon;
10215
- const { useEffect: useEffect80, useRef: useRef81, useCallback: useCallback105, useState: useState106 } = React118__namespace.default;
10216
+ const { useEffect: useEffect81, useRef: useRef81, useCallback: useCallback105, useState: useState107 } = React118__namespace.default;
10216
10217
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
10217
10218
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
10218
10219
  function MapUpdater({ centerLat, centerLng, zoom }) {
10219
10220
  const map = useMap();
10220
10221
  const prevRef = useRef81({ centerLat, centerLng, zoom });
10221
- useEffect80(() => {
10222
+ useEffect81(() => {
10222
10223
  const prev = prevRef.current;
10223
10224
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
10224
10225
  map.setView([centerLat, centerLng], zoom);
@@ -10229,7 +10230,7 @@ var init_MapView = __esm({
10229
10230
  }
10230
10231
  function MapClickHandler({ onMapClick }) {
10231
10232
  const map = useMap();
10232
- useEffect80(() => {
10233
+ useEffect81(() => {
10233
10234
  if (!onMapClick) return;
10234
10235
  const handler = (e) => {
10235
10236
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -10256,7 +10257,7 @@ var init_MapView = __esm({
10256
10257
  showAttribution = true
10257
10258
  }) {
10258
10259
  const eventBus = useEventBus3();
10259
- const [clickedPosition, setClickedPosition] = useState106(null);
10260
+ const [clickedPosition, setClickedPosition] = useState107(null);
10260
10261
  const handleMapClick = useCallback105((lat, lng) => {
10261
10262
  if (showClickedPin) {
10262
10263
  setClickedPosition({ lat, lng });
@@ -12837,9 +12838,9 @@ var init_ScaledDiagram = __esm({
12837
12838
  }
12838
12839
  });
12839
12840
 
12840
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
12841
+ // node_modules/katex/dist/katex.min.css
12841
12842
  var init_katex_min = __esm({
12842
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
12843
+ "node_modules/katex/dist/katex.min.css"() {
12843
12844
  }
12844
12845
  });
12845
12846
  var MarkdownContent;
@@ -20636,6 +20637,7 @@ var init_DashboardLayout = __esm({
20636
20637
  showSearch = false,
20637
20638
  searchEvent,
20638
20639
  onSearchSubmit,
20640
+ topBarActions = [],
20639
20641
  notifications,
20640
20642
  notificationClickEvent,
20641
20643
  onNotificationClick,
@@ -20656,6 +20658,9 @@ var init_DashboardLayout = __esm({
20656
20658
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
20657
20659
  if (onNotificationClick) onNotificationClick();
20658
20660
  };
20661
+ const handleTopBarActionClick = (event) => {
20662
+ eventBus.emit(`UI:${event}`, {});
20663
+ };
20659
20664
  const [sidebarOpen, setSidebarOpen] = React118.useState(false);
20660
20665
  const [userMenuOpen, setUserMenuOpen] = React118.useState(false);
20661
20666
  const location = reactRouterDom.useLocation();
@@ -20782,6 +20787,30 @@ var init_DashboardLayout = __esm({
20782
20787
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "xs", children: [
20783
20788
  headerActions,
20784
20789
  showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
20790
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
20791
+ Button,
20792
+ {
20793
+ variant: "ghost",
20794
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
20795
+ onClick: () => handleTopBarActionClick(action.event),
20796
+ "aria-label": action.label ?? action.icon,
20797
+ children: [
20798
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
20799
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsxRuntime.jsx(
20800
+ Box,
20801
+ {
20802
+ as: "span",
20803
+ className: cn(
20804
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
20805
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
20806
+ ),
20807
+ children: action.badge
20808
+ }
20809
+ )
20810
+ ]
20811
+ },
20812
+ `${action.event}-${idx}`
20813
+ )),
20785
20814
  notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
20786
20815
  Button,
20787
20816
  {
@@ -50322,6 +50351,48 @@ function OrbPreview({
50322
50351
  );
50323
50352
  }
50324
50353
  OrbPreview.displayName = "OrbPreview";
50354
+ function BrowserPlayground({
50355
+ schema,
50356
+ mode = "mock",
50357
+ initialPagePath,
50358
+ height,
50359
+ className
50360
+ }) {
50361
+ const [runtime] = React118.useState(
50362
+ () => new OrbitalServerRuntime.OrbitalServerRuntime({ mode, debug: false })
50363
+ );
50364
+ React118.useEffect(() => {
50365
+ void runtime.register(schema);
50366
+ return () => {
50367
+ runtime.unregisterAll();
50368
+ };
50369
+ }, [runtime, schema]);
50370
+ const transport = React118.useMemo(() => ({
50371
+ register: async (s) => {
50372
+ await runtime.register(s);
50373
+ return true;
50374
+ },
50375
+ unregister: async () => {
50376
+ runtime.unregisterAll();
50377
+ },
50378
+ sendEvent: async (orbitalName, event, payload) => {
50379
+ return runtime.processOrbitalEvent(orbitalName, {
50380
+ event,
50381
+ payload
50382
+ });
50383
+ }
50384
+ }), [runtime]);
50385
+ return /* @__PURE__ */ jsxRuntime.jsx(
50386
+ OrbPreview,
50387
+ {
50388
+ schema,
50389
+ transport,
50390
+ initialPagePath,
50391
+ height,
50392
+ className
50393
+ }
50394
+ );
50395
+ }
50325
50396
 
50326
50397
  // components/molecules/avl/OrbPreviewNode.tsx
50327
50398
  init_useEventBus();
@@ -50502,7 +50573,6 @@ var OrbPreviewNodeInner = (props) => {
50502
50573
  }
50503
50574
  return buildOrbitalSchema(fullSchema, data.orbitalName);
50504
50575
  }, [data._fullSchema, data.orbitalName, data.traitName, data.transitionEvent, data.fromState, data.toState, isExpanded]);
50505
- const mockData = data._mockData ?? void 0;
50506
50576
  const handleContentClick = React118.useCallback((e) => {
50507
50577
  e.stopPropagation();
50508
50578
  const target = e.target;
@@ -50676,10 +50746,10 @@ var OrbPreviewNodeInner = (props) => {
50676
50746
  onDragOver: handlePreviewDragOver,
50677
50747
  onDragLeave: handlePreviewDragLeave,
50678
50748
  children: orbitalSchema ? /* @__PURE__ */ jsxRuntime.jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsxRuntime.jsx(
50679
- OrbPreview,
50749
+ BrowserPlayground,
50680
50750
  {
50681
50751
  schema: orbitalSchema,
50682
- mockData,
50752
+ mode: "mock",
50683
50753
  height: "auto"
50684
50754
  }
50685
50755
  ) }) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center justify-center", style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "text-muted-foreground", children: "No preview available" }) })
@@ -1,4 +1,4 @@
1
- /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
package/dist/avl/index.js CHANGED
@@ -42,6 +42,7 @@ import { EffectComposer, Bloom, DepthOfField, Vignette } from '@react-three/post
42
42
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
43
43
  import ELK from 'elkjs/lib/elk.bundled.js';
44
44
  import { MarkerType, Handle, Position, getBezierPath, EdgeLabelRenderer, BaseEdge, ReactFlowProvider, useNodesState, useEdgesState, useReactFlow, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
45
+ import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
45
46
  import { InMemoryPersistence, StateMachineManager, createContextFromBindings, interpolateValue, collectDeclaredConfigDefaults, createServerEffectHandlers, EffectExecutor } from '@almadar/runtime';
46
47
 
47
48
  var __defProp = Object.defineProperty;
@@ -135,7 +136,7 @@ var init_types = __esm({
135
136
  }
136
137
  });
137
138
 
138
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
139
+ // node_modules/clsx/dist/clsx.mjs
139
140
  function r(e) {
140
141
  var t, f, n = "";
141
142
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -150,11 +151,11 @@ function clsx() {
150
151
  return n;
151
152
  }
152
153
  var init_clsx = __esm({
153
- "node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs"() {
154
+ "node_modules/clsx/dist/clsx.mjs"() {
154
155
  }
155
156
  });
156
157
 
157
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
158
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
158
159
  function twJoin() {
159
160
  let index = 0;
160
161
  let argument;
@@ -198,7 +199,7 @@ function createTailwindMerge(createConfigFirst, ...createConfigRest) {
198
199
  }
199
200
  var CLASS_PART_SEPARATOR, createClassGroupUtils, getGroupRecursive, arbitraryPropertyRegex, getGroupIdForArbitraryProperty, createClassMap, processClassesRecursively, getPart, isThemeGetter, getPrefixedClassGroupEntries, createLruCache, IMPORTANT_MODIFIER, createParseClassName, sortModifiers, createConfigUtils, SPLIT_CLASSES_REGEX, mergeClassList, toValue, fromTheme, arbitraryValueRegex, fractionRegex, stringLengths, tshirtUnitRegex, lengthUnitRegex, colorFunctionRegex, shadowRegex, imageRegex, isLength, isArbitraryLength, isNumber, isArbitraryNumber, isInteger, isPercent, isArbitraryValue, isTshirtSize, sizeLabels, isArbitrarySize, isArbitraryPosition, imageLabels, isArbitraryImage, isArbitraryShadow, isAny, getIsArbitraryValue, isLengthOnly, isNever, isShadow, isImage, getDefaultConfig, twMerge;
200
201
  var init_bundle_mjs = __esm({
201
- "node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
202
+ "node_modules/tailwind-merge/dist/bundle-mjs.mjs"() {
202
203
  CLASS_PART_SEPARATOR = "-";
203
204
  createClassGroupUtils = (config) => {
204
205
  const classMap = createClassMap(config);
@@ -10166,13 +10167,13 @@ var init_MapView = __esm({
10166
10167
  shadowSize: [41, 41]
10167
10168
  });
10168
10169
  L.Marker.prototype.options.icon = defaultIcon;
10169
- const { useEffect: useEffect80, useRef: useRef81, useCallback: useCallback105, useState: useState106 } = React118__default;
10170
+ const { useEffect: useEffect81, useRef: useRef81, useCallback: useCallback105, useState: useState107 } = React118__default;
10170
10171
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
10171
10172
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
10172
10173
  function MapUpdater({ centerLat, centerLng, zoom }) {
10173
10174
  const map = useMap();
10174
10175
  const prevRef = useRef81({ centerLat, centerLng, zoom });
10175
- useEffect80(() => {
10176
+ useEffect81(() => {
10176
10177
  const prev = prevRef.current;
10177
10178
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
10178
10179
  map.setView([centerLat, centerLng], zoom);
@@ -10183,7 +10184,7 @@ var init_MapView = __esm({
10183
10184
  }
10184
10185
  function MapClickHandler({ onMapClick }) {
10185
10186
  const map = useMap();
10186
- useEffect80(() => {
10187
+ useEffect81(() => {
10187
10188
  if (!onMapClick) return;
10188
10189
  const handler = (e) => {
10189
10190
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -10210,7 +10211,7 @@ var init_MapView = __esm({
10210
10211
  showAttribution = true
10211
10212
  }) {
10212
10213
  const eventBus = useEventBus3();
10213
- const [clickedPosition, setClickedPosition] = useState106(null);
10214
+ const [clickedPosition, setClickedPosition] = useState107(null);
10214
10215
  const handleMapClick = useCallback105((lat, lng) => {
10215
10216
  if (showClickedPin) {
10216
10217
  setClickedPosition({ lat, lng });
@@ -12791,9 +12792,9 @@ var init_ScaledDiagram = __esm({
12791
12792
  }
12792
12793
  });
12793
12794
 
12794
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
12795
+ // node_modules/katex/dist/katex.min.css
12795
12796
  var init_katex_min = __esm({
12796
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
12797
+ "node_modules/katex/dist/katex.min.css"() {
12797
12798
  }
12798
12799
  });
12799
12800
  var MarkdownContent;
@@ -20590,6 +20591,7 @@ var init_DashboardLayout = __esm({
20590
20591
  showSearch = false,
20591
20592
  searchEvent,
20592
20593
  onSearchSubmit,
20594
+ topBarActions = [],
20593
20595
  notifications,
20594
20596
  notificationClickEvent,
20595
20597
  onNotificationClick,
@@ -20610,6 +20612,9 @@ var init_DashboardLayout = __esm({
20610
20612
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
20611
20613
  if (onNotificationClick) onNotificationClick();
20612
20614
  };
20615
+ const handleTopBarActionClick = (event) => {
20616
+ eventBus.emit(`UI:${event}`, {});
20617
+ };
20613
20618
  const [sidebarOpen, setSidebarOpen] = useState(false);
20614
20619
  const [userMenuOpen, setUserMenuOpen] = useState(false);
20615
20620
  const location = useLocation();
@@ -20736,6 +20741,30 @@ var init_DashboardLayout = __esm({
20736
20741
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
20737
20742
  headerActions,
20738
20743
  showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
20744
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxs(
20745
+ Button,
20746
+ {
20747
+ variant: "ghost",
20748
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
20749
+ onClick: () => handleTopBarActionClick(action.event),
20750
+ "aria-label": action.label ?? action.icon,
20751
+ children: [
20752
+ /* @__PURE__ */ jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
20753
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsx(
20754
+ Box,
20755
+ {
20756
+ as: "span",
20757
+ className: cn(
20758
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
20759
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
20760
+ ),
20761
+ children: action.badge
20762
+ }
20763
+ )
20764
+ ]
20765
+ },
20766
+ `${action.event}-${idx}`
20767
+ )),
20739
20768
  notificationsEnabled && /* @__PURE__ */ jsxs(
20740
20769
  Button,
20741
20770
  {
@@ -50276,6 +50305,48 @@ function OrbPreview({
50276
50305
  );
50277
50306
  }
50278
50307
  OrbPreview.displayName = "OrbPreview";
50308
+ function BrowserPlayground({
50309
+ schema,
50310
+ mode = "mock",
50311
+ initialPagePath,
50312
+ height,
50313
+ className
50314
+ }) {
50315
+ const [runtime] = useState(
50316
+ () => new OrbitalServerRuntime({ mode, debug: false })
50317
+ );
50318
+ useEffect(() => {
50319
+ void runtime.register(schema);
50320
+ return () => {
50321
+ runtime.unregisterAll();
50322
+ };
50323
+ }, [runtime, schema]);
50324
+ const transport = useMemo(() => ({
50325
+ register: async (s) => {
50326
+ await runtime.register(s);
50327
+ return true;
50328
+ },
50329
+ unregister: async () => {
50330
+ runtime.unregisterAll();
50331
+ },
50332
+ sendEvent: async (orbitalName, event, payload) => {
50333
+ return runtime.processOrbitalEvent(orbitalName, {
50334
+ event,
50335
+ payload
50336
+ });
50337
+ }
50338
+ }), [runtime]);
50339
+ return /* @__PURE__ */ jsx(
50340
+ OrbPreview,
50341
+ {
50342
+ schema,
50343
+ transport,
50344
+ initialPagePath,
50345
+ height,
50346
+ className
50347
+ }
50348
+ );
50349
+ }
50279
50350
 
50280
50351
  // components/molecules/avl/OrbPreviewNode.tsx
50281
50352
  init_useEventBus();
@@ -50456,7 +50527,6 @@ var OrbPreviewNodeInner = (props) => {
50456
50527
  }
50457
50528
  return buildOrbitalSchema(fullSchema, data.orbitalName);
50458
50529
  }, [data._fullSchema, data.orbitalName, data.traitName, data.transitionEvent, data.fromState, data.toState, isExpanded]);
50459
- const mockData = data._mockData ?? void 0;
50460
50530
  const handleContentClick = useCallback((e) => {
50461
50531
  e.stopPropagation();
50462
50532
  const target = e.target;
@@ -50630,10 +50700,10 @@ var OrbPreviewNodeInner = (props) => {
50630
50700
  onDragOver: handlePreviewDragOver,
50631
50701
  onDragLeave: handlePreviewDragLeave,
50632
50702
  children: orbitalSchema ? /* @__PURE__ */ jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(
50633
- OrbPreview,
50703
+ BrowserPlayground,
50634
50704
  {
50635
50705
  schema: orbitalSchema,
50636
- mockData,
50706
+ mode: "mock",
50637
50707
  height: "auto"
50638
50708
  }
50639
50709
  ) }) : /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center", style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground", children: "No preview available" }) })
@@ -8974,9 +8974,9 @@ var init_ScaledDiagram = __esm({
8974
8974
  }
8975
8975
  });
8976
8976
 
8977
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
8977
+ // node_modules/katex/dist/katex.min.css
8978
8978
  var init_katex_min = __esm({
8979
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
8979
+ "node_modules/katex/dist/katex.min.css"() {
8980
8980
  }
8981
8981
  });
8982
8982
  exports.MarkdownContent = void 0;
@@ -17000,6 +17000,7 @@ var init_DashboardLayout = __esm({
17000
17000
  showSearch = false,
17001
17001
  searchEvent,
17002
17002
  onSearchSubmit,
17003
+ topBarActions = [],
17003
17004
  notifications,
17004
17005
  notificationClickEvent,
17005
17006
  onNotificationClick,
@@ -17020,6 +17021,9 @@ var init_DashboardLayout = __esm({
17020
17021
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
17021
17022
  if (onNotificationClick) onNotificationClick();
17022
17023
  };
17024
+ const handleTopBarActionClick = (event) => {
17025
+ eventBus.emit(`UI:${event}`, {});
17026
+ };
17023
17027
  const [sidebarOpen, setSidebarOpen] = React109.useState(false);
17024
17028
  const [userMenuOpen, setUserMenuOpen] = React109.useState(false);
17025
17029
  const location = reactRouterDom.useLocation();
@@ -17150,6 +17154,30 @@ var init_DashboardLayout = __esm({
17150
17154
  /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { align: "center", gap: "xs", children: [
17151
17155
  headerActions,
17152
17156
  showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(exports.ThemeToggle, {}),
17157
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
17158
+ exports.Button,
17159
+ {
17160
+ variant: "ghost",
17161
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17162
+ onClick: () => handleTopBarActionClick(action.event),
17163
+ "aria-label": action.label ?? action.icon,
17164
+ children: [
17165
+ /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17166
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsxRuntime.jsx(
17167
+ exports.Box,
17168
+ {
17169
+ as: "span",
17170
+ className: cn(
17171
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17172
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17173
+ ),
17174
+ children: action.badge
17175
+ }
17176
+ )
17177
+ ]
17178
+ },
17179
+ `${action.event}-${idx}`
17180
+ )),
17153
17181
  notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
17154
17182
  exports.Button,
17155
17183
  {
@@ -1,4 +1,4 @@
1
- /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -8929,9 +8929,9 @@ var init_ScaledDiagram = __esm({
8929
8929
  }
8930
8930
  });
8931
8931
 
8932
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
8932
+ // node_modules/katex/dist/katex.min.css
8933
8933
  var init_katex_min = __esm({
8934
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
8934
+ "node_modules/katex/dist/katex.min.css"() {
8935
8935
  }
8936
8936
  });
8937
8937
  var MarkdownContent;
@@ -16955,6 +16955,7 @@ var init_DashboardLayout = __esm({
16955
16955
  showSearch = false,
16956
16956
  searchEvent,
16957
16957
  onSearchSubmit,
16958
+ topBarActions = [],
16958
16959
  notifications,
16959
16960
  notificationClickEvent,
16960
16961
  onNotificationClick,
@@ -16975,6 +16976,9 @@ var init_DashboardLayout = __esm({
16975
16976
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
16976
16977
  if (onNotificationClick) onNotificationClick();
16977
16978
  };
16979
+ const handleTopBarActionClick = (event) => {
16980
+ eventBus.emit(`UI:${event}`, {});
16981
+ };
16978
16982
  const [sidebarOpen, setSidebarOpen] = useState(false);
16979
16983
  const [userMenuOpen, setUserMenuOpen] = useState(false);
16980
16984
  const location = useLocation();
@@ -17105,6 +17109,30 @@ var init_DashboardLayout = __esm({
17105
17109
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
17106
17110
  headerActions,
17107
17111
  showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
17112
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxs(
17113
+ Button,
17114
+ {
17115
+ variant: "ghost",
17116
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17117
+ onClick: () => handleTopBarActionClick(action.event),
17118
+ "aria-label": action.label ?? action.icon,
17119
+ children: [
17120
+ /* @__PURE__ */ jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17121
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsx(
17122
+ Box,
17123
+ {
17124
+ as: "span",
17125
+ className: cn(
17126
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17127
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17128
+ ),
17129
+ children: action.badge
17130
+ }
17131
+ )
17132
+ ]
17133
+ },
17134
+ `${action.event}-${idx}`
17135
+ )),
17108
17136
  notificationsEnabled && /* @__PURE__ */ jsxs(
17109
17137
  Button,
17110
17138
  {
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import { LucideIcon } from "lucide-react";
3
- import type { EventEmit } from "@almadar/core";
3
+ import type { EventEmit, EventKey } from "@almadar/core";
4
4
  export interface NavItem {
5
5
  label: string;
6
6
  href: string;
@@ -20,6 +20,25 @@ export interface NotificationItem {
20
20
  /** Optional flag — bell badge counts items where read !== true. */
21
21
  read?: boolean;
22
22
  }
23
+ /** A generic top-bar action button. Domain-agnostic — consumers wire any
24
+ * combination (cart icon, profile, help, custom). Each entry renders as
25
+ * an icon button between the search bar and the notifications bell;
26
+ * click dispatches the configured event onto the bus. */
27
+ export interface TopBarAction {
28
+ /** Lucide icon name (e.g. "shopping-cart", "user", "help-circle"). */
29
+ icon: string;
30
+ /** Optional aria-label / tooltip. Falls back to `icon`. */
31
+ label?: string;
32
+ /** Bus event fired on click. Dispatched as `UI:{event}` with empty payload.
33
+ * Typed as `EventKey` so the pattern-sync detector marks `topBarActions`
34
+ * as `event-list` and the validator checks references against trait
35
+ * emit/listen sets. */
36
+ event: EventKey;
37
+ /** Optional badge — number or string rendered in the corner of the icon. */
38
+ badge?: number | string;
39
+ /** Visual variant. Default `"default"`. */
40
+ variant?: "default" | "primary" | "danger";
41
+ }
23
42
  export interface DashboardLayoutProps {
24
43
  /** App name shown in sidebar */
25
44
  appName?: string;
@@ -49,6 +68,12 @@ export interface DashboardLayoutProps {
49
68
  /** React-side search submit callback. Used when the host wires the
50
69
  * layout directly (not via render-ui pattern resolution). */
51
70
  onSearchSubmit?: (value: string) => void;
71
+ /** Generic top-bar action buttons rendered between the search bar and
72
+ * the notifications bell. Each entry: `{icon, label?, event, badge?, variant?}`.
73
+ * Domain-agnostic — consumers add a cart icon, profile button, help-bubble,
74
+ * or any other top-bar action by appending entries. Empty array (default)
75
+ * renders nothing. */
76
+ topBarActions?: TopBarAction[];
52
77
  /** Notification list. Pass an empty array to show the bell with no
53
78
  * badge; omit / pass null to hide the bell entirely. */
54
79
  notifications?: NotificationItem[] | null;
@@ -27,7 +27,7 @@ function _interopNamespace(e) {
27
27
  var React5__default = /*#__PURE__*/_interopDefault(React5);
28
28
  var LucideIcons__namespace = /*#__PURE__*/_interopNamespace(LucideIcons);
29
29
 
30
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
30
+ // node_modules/clsx/dist/clsx.mjs
31
31
  function r(e) {
32
32
  var t, f, n = "";
33
33
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -42,7 +42,7 @@ function clsx() {
42
42
  return n;
43
43
  }
44
44
 
45
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
45
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
46
46
  var CLASS_PART_SEPARATOR = "-";
47
47
  var createClassGroupUtils = (config) => {
48
48
  const classMap = createClassMap(config);
@@ -3,7 +3,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
3
3
  import * as LucideIcons from 'lucide-react';
4
4
  import { Loader2, ChevronDown, X } from 'lucide-react';
5
5
 
6
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
6
+ // node_modules/clsx/dist/clsx.mjs
7
7
  function r(e) {
8
8
  var t, f, n = "";
9
9
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -18,7 +18,7 @@ function clsx() {
18
18
  return n;
19
19
  }
20
20
 
21
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
21
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
22
22
  var CLASS_PART_SEPARATOR = "-";
23
23
  var createClassGroupUtils = (config) => {
24
24
  const classMap = createClassMap(config);
@@ -27,7 +27,7 @@ function _interopNamespace(e) {
27
27
  var React6__default = /*#__PURE__*/_interopDefault(React6);
28
28
  var LucideIcons__namespace = /*#__PURE__*/_interopNamespace(LucideIcons);
29
29
 
30
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
30
+ // node_modules/clsx/dist/clsx.mjs
31
31
  function r(e) {
32
32
  var t, f3, n = "";
33
33
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -42,7 +42,7 @@ function clsx() {
42
42
  return n;
43
43
  }
44
44
 
45
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
45
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
46
46
  var CLASS_PART_SEPARATOR = "-";
47
47
  var createClassGroupUtils = (config) => {
48
48
  const classMap = createClassMap(config);
@@ -3,7 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import * as LucideIcons from 'lucide-react';
4
4
  import { Loader2, Check, User } from 'lucide-react';
5
5
 
6
- // node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
6
+ // node_modules/clsx/dist/clsx.mjs
7
7
  function r(e) {
8
8
  var t, f3, n = "";
9
9
  if ("string" == typeof e || "number" == typeof e) n += e;
@@ -18,7 +18,7 @@ function clsx() {
18
18
  return n;
19
19
  }
20
20
 
21
- // node_modules/.pnpm/tailwind-merge@2.6.1/node_modules/tailwind-merge/dist/bundle-mjs.mjs
21
+ // node_modules/tailwind-merge/dist/bundle-mjs.mjs
22
22
  var CLASS_PART_SEPARATOR = "-";
23
23
  var createClassGroupUtils = (config) => {
24
24
  const classMap = createClassMap(config);
@@ -9595,9 +9595,9 @@ var init_ScaledDiagram = __esm({
9595
9595
  }
9596
9596
  });
9597
9597
 
9598
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9598
+ // node_modules/katex/dist/katex.min.css
9599
9599
  var init_katex_min = __esm({
9600
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9600
+ "node_modules/katex/dist/katex.min.css"() {
9601
9601
  }
9602
9602
  });
9603
9603
  var MarkdownContent;
@@ -17394,6 +17394,7 @@ var init_DashboardLayout = __esm({
17394
17394
  showSearch = false,
17395
17395
  searchEvent,
17396
17396
  onSearchSubmit,
17397
+ topBarActions = [],
17397
17398
  notifications,
17398
17399
  notificationClickEvent,
17399
17400
  onNotificationClick,
@@ -17414,6 +17415,9 @@ var init_DashboardLayout = __esm({
17414
17415
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
17415
17416
  if (onNotificationClick) onNotificationClick();
17416
17417
  };
17418
+ const handleTopBarActionClick = (event) => {
17419
+ eventBus.emit(`UI:${event}`, {});
17420
+ };
17417
17421
  const [sidebarOpen, setSidebarOpen] = React105.useState(false);
17418
17422
  const [userMenuOpen, setUserMenuOpen] = React105.useState(false);
17419
17423
  const location = reactRouterDom.useLocation();
@@ -17540,6 +17544,30 @@ var init_DashboardLayout = __esm({
17540
17544
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "xs", children: [
17541
17545
  headerActions,
17542
17546
  showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
17547
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
17548
+ Button,
17549
+ {
17550
+ variant: "ghost",
17551
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17552
+ onClick: () => handleTopBarActionClick(action.event),
17553
+ "aria-label": action.label ?? action.icon,
17554
+ children: [
17555
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17556
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsxRuntime.jsx(
17557
+ Box,
17558
+ {
17559
+ as: "span",
17560
+ className: cn(
17561
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17562
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17563
+ ),
17564
+ children: action.badge
17565
+ }
17566
+ )
17567
+ ]
17568
+ },
17569
+ `${action.event}-${idx}`
17570
+ )),
17543
17571
  notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
17544
17572
  Button,
17545
17573
  {
@@ -1,4 +1,4 @@
1
- /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -9550,9 +9550,9 @@ var init_ScaledDiagram = __esm({
9550
9550
  }
9551
9551
  });
9552
9552
 
9553
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9553
+ // node_modules/katex/dist/katex.min.css
9554
9554
  var init_katex_min = __esm({
9555
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9555
+ "node_modules/katex/dist/katex.min.css"() {
9556
9556
  }
9557
9557
  });
9558
9558
  var MarkdownContent;
@@ -17349,6 +17349,7 @@ var init_DashboardLayout = __esm({
17349
17349
  showSearch = false,
17350
17350
  searchEvent,
17351
17351
  onSearchSubmit,
17352
+ topBarActions = [],
17352
17353
  notifications,
17353
17354
  notificationClickEvent,
17354
17355
  onNotificationClick,
@@ -17369,6 +17370,9 @@ var init_DashboardLayout = __esm({
17369
17370
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
17370
17371
  if (onNotificationClick) onNotificationClick();
17371
17372
  };
17373
+ const handleTopBarActionClick = (event) => {
17374
+ eventBus.emit(`UI:${event}`, {});
17375
+ };
17372
17376
  const [sidebarOpen, setSidebarOpen] = useState(false);
17373
17377
  const [userMenuOpen, setUserMenuOpen] = useState(false);
17374
17378
  const location = useLocation();
@@ -17495,6 +17499,30 @@ var init_DashboardLayout = __esm({
17495
17499
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
17496
17500
  headerActions,
17497
17501
  showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
17502
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxs(
17503
+ Button,
17504
+ {
17505
+ variant: "ghost",
17506
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17507
+ onClick: () => handleTopBarActionClick(action.event),
17508
+ "aria-label": action.label ?? action.icon,
17509
+ children: [
17510
+ /* @__PURE__ */ jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17511
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsx(
17512
+ Box,
17513
+ {
17514
+ as: "span",
17515
+ className: cn(
17516
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17517
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17518
+ ),
17519
+ children: action.badge
17520
+ }
17521
+ )
17522
+ ]
17523
+ },
17524
+ `${action.event}-${idx}`
17525
+ )),
17498
17526
  notificationsEnabled && /* @__PURE__ */ jsxs(
17499
17527
  Button,
17500
17528
  {
@@ -9495,9 +9495,9 @@ var init_ScaledDiagram = __esm({
9495
9495
  }
9496
9496
  });
9497
9497
 
9498
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9498
+ // node_modules/katex/dist/katex.min.css
9499
9499
  var init_katex_min = __esm({
9500
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9500
+ "node_modules/katex/dist/katex.min.css"() {
9501
9501
  }
9502
9502
  });
9503
9503
  var MarkdownContent;
@@ -17163,6 +17163,7 @@ var init_DashboardLayout = __esm({
17163
17163
  showSearch = false,
17164
17164
  searchEvent,
17165
17165
  onSearchSubmit,
17166
+ topBarActions = [],
17166
17167
  notifications,
17167
17168
  notificationClickEvent,
17168
17169
  onNotificationClick,
@@ -17183,6 +17184,9 @@ var init_DashboardLayout = __esm({
17183
17184
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
17184
17185
  if (onNotificationClick) onNotificationClick();
17185
17186
  };
17187
+ const handleTopBarActionClick = (event) => {
17188
+ eventBus.emit(`UI:${event}`, {});
17189
+ };
17186
17190
  const [sidebarOpen, setSidebarOpen] = React104.useState(false);
17187
17191
  const [userMenuOpen, setUserMenuOpen] = React104.useState(false);
17188
17192
  const location = reactRouterDom.useLocation();
@@ -17309,6 +17313,30 @@ var init_DashboardLayout = __esm({
17309
17313
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "xs", children: [
17310
17314
  headerActions,
17311
17315
  showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
17316
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
17317
+ Button,
17318
+ {
17319
+ variant: "ghost",
17320
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17321
+ onClick: () => handleTopBarActionClick(action.event),
17322
+ "aria-label": action.label ?? action.icon,
17323
+ children: [
17324
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17325
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsxRuntime.jsx(
17326
+ Box,
17327
+ {
17328
+ as: "span",
17329
+ className: cn(
17330
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17331
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17332
+ ),
17333
+ children: action.badge
17334
+ }
17335
+ )
17336
+ ]
17337
+ },
17338
+ `${action.event}-${idx}`
17339
+ )),
17312
17340
  notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
17313
17341
  Button,
17314
17342
  {
@@ -1,4 +1,4 @@
1
- /* node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css */
1
+ /* node_modules/katex/dist/katex.min.css */
2
2
  @font-face {
3
3
  font-display: block;
4
4
  font-family: KaTeX_AMS;
@@ -9450,9 +9450,9 @@ var init_ScaledDiagram = __esm({
9450
9450
  }
9451
9451
  });
9452
9452
 
9453
- // node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css
9453
+ // node_modules/katex/dist/katex.min.css
9454
9454
  var init_katex_min = __esm({
9455
- "node_modules/.pnpm/katex@0.16.45/node_modules/katex/dist/katex.min.css"() {
9455
+ "node_modules/katex/dist/katex.min.css"() {
9456
9456
  }
9457
9457
  });
9458
9458
  var MarkdownContent;
@@ -17118,6 +17118,7 @@ var init_DashboardLayout = __esm({
17118
17118
  showSearch = false,
17119
17119
  searchEvent,
17120
17120
  onSearchSubmit,
17121
+ topBarActions = [],
17121
17122
  notifications,
17122
17123
  notificationClickEvent,
17123
17124
  onNotificationClick,
@@ -17138,6 +17139,9 @@ var init_DashboardLayout = __esm({
17138
17139
  if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
17139
17140
  if (onNotificationClick) onNotificationClick();
17140
17141
  };
17142
+ const handleTopBarActionClick = (event) => {
17143
+ eventBus.emit(`UI:${event}`, {});
17144
+ };
17141
17145
  const [sidebarOpen, setSidebarOpen] = useState(false);
17142
17146
  const [userMenuOpen, setUserMenuOpen] = useState(false);
17143
17147
  const location = useLocation();
@@ -17264,6 +17268,30 @@ var init_DashboardLayout = __esm({
17264
17268
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
17265
17269
  headerActions,
17266
17270
  showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
17271
+ topBarActions.map((action, idx) => /* @__PURE__ */ jsxs(
17272
+ Button,
17273
+ {
17274
+ variant: "ghost",
17275
+ className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
17276
+ onClick: () => handleTopBarActionClick(action.event),
17277
+ "aria-label": action.label ?? action.icon,
17278
+ children: [
17279
+ /* @__PURE__ */ jsx(Icon, { name: action.icon, className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
17280
+ action.badge !== void 0 && action.badge !== null && action.badge !== 0 && action.badge !== "" && /* @__PURE__ */ jsx(
17281
+ Box,
17282
+ {
17283
+ as: "span",
17284
+ className: cn(
17285
+ "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
17286
+ action.variant === "danger" ? "bg-error" : action.variant === "primary" ? "bg-primary" : "bg-foreground"
17287
+ ),
17288
+ children: action.badge
17289
+ }
17290
+ )
17291
+ ]
17292
+ },
17293
+ `${action.event}-${idx}`
17294
+ )),
17267
17295
  notificationsEnabled && /* @__PURE__ */ jsxs(
17268
17296
  Button,
17269
17297
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.26.0",
3
+ "version": "4.27.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -121,6 +121,13 @@
121
121
  "registry": "https://registry.npmjs.org",
122
122
  "access": "public"
123
123
  },
124
+ "scripts": {
125
+ "build": "tsup && tsc -p tsconfig.build.json",
126
+ "build:watch": "tsup --watch",
127
+ "storybook": "storybook dev -p 6006",
128
+ "build-storybook": "storybook build -o storybook-static",
129
+ "typecheck": "tsc --noEmit"
130
+ },
124
131
  "dependencies": {
125
132
  "@almadar/core": ">=7.12.0",
126
133
  "@almadar/evaluator": ">=2.9.2",
@@ -212,11 +219,10 @@
212
219
  "hooks"
213
220
  ],
214
221
  "homepage": "https://github.com/almadar-io/almadar#readme",
215
- "scripts": {
216
- "build": "tsup && tsc -p tsconfig.build.json",
217
- "build:watch": "tsup --watch",
218
- "storybook": "storybook dev -p 6006",
219
- "build-storybook": "storybook build -o storybook-static",
220
- "typecheck": "tsc --noEmit"
222
+ "pnpm": {
223
+ "overrides": {
224
+ "@types/react": "^19.0.0",
225
+ "@types/react-dom": "^19.0.0"
226
+ }
221
227
  }
222
- }
228
+ }