@almadar/ui 6.26.0 → 6.28.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.
@@ -31971,6 +31971,247 @@ var init_WizardNavigation = __esm({
31971
31971
  WizardNavigation.displayName = "WizardNavigation";
31972
31972
  }
31973
31973
  });
31974
+ function parseDay(value) {
31975
+ if (value === void 0 || value === null || value === "") return null;
31976
+ const d = value instanceof Date ? new Date(value.getTime()) : new Date(value);
31977
+ if (Number.isNaN(d.getTime())) return null;
31978
+ d.setHours(0, 0, 0, 0);
31979
+ return d;
31980
+ }
31981
+ function Gantt({
31982
+ tasks = [],
31983
+ links = [],
31984
+ titleField = "title",
31985
+ startField = "start",
31986
+ endField = "end",
31987
+ durationField,
31988
+ statusField = "status",
31989
+ groupField = "",
31990
+ rangeStart,
31991
+ rangeEnd,
31992
+ showToday = true,
31993
+ dayWidth = 28,
31994
+ barClickEvent,
31995
+ className,
31996
+ isLoading = false,
31997
+ error = null
31998
+ }) {
31999
+ const { t } = useTranslate();
32000
+ const placed = useMemo(() => {
32001
+ const rows = Array.isArray(tasks) ? tasks : tasks ? [tasks] : [];
32002
+ const out = [];
32003
+ rows.forEach((row, idx) => {
32004
+ const start = parseDay(getNestedValue(row, startField));
32005
+ if (!start) return;
32006
+ let end = parseDay(getNestedValue(row, endField));
32007
+ if (!end && durationField) {
32008
+ const days2 = Number(getNestedValue(row, durationField));
32009
+ if (Number.isFinite(days2) && days2 > 0) {
32010
+ end = new Date(start.getTime() + days2 * DAY_MS);
32011
+ }
32012
+ }
32013
+ if (!end || end.getTime() < start.getTime()) end = new Date(start.getTime() + DAY_MS);
32014
+ out.push({
32015
+ row,
32016
+ id: String(row.id ?? idx),
32017
+ label: String(getNestedValue(row, titleField) ?? ""),
32018
+ status: String(getNestedValue(row, statusField) ?? "").toLowerCase(),
32019
+ group: groupField ? String(getNestedValue(row, groupField) ?? "") : "",
32020
+ start,
32021
+ end
32022
+ });
32023
+ });
32024
+ return out;
32025
+ }, [tasks, titleField, startField, endField, durationField, statusField, groupField]);
32026
+ const [axisStart, axisEnd] = useMemo(() => {
32027
+ const lo = parseDay(rangeStart) ?? (placed.length ? new Date(Math.min(...placed.map((p) => p.start.getTime())) - 2 * DAY_MS) : new Date((/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0)));
32028
+ const hi = parseDay(rangeEnd) ?? (placed.length ? new Date(Math.max(...placed.map((p) => p.end.getTime())) + 2 * DAY_MS) : new Date(lo.getTime() + 30 * DAY_MS));
32029
+ return hi.getTime() > lo.getTime() ? [lo, hi] : [lo, new Date(lo.getTime() + DAY_MS)];
32030
+ }, [rangeStart, rangeEnd, placed]);
32031
+ const totalDays = Math.round((axisEnd.getTime() - axisStart.getTime()) / DAY_MS);
32032
+ const chartWidth = totalDays * dayWidth;
32033
+ const dayOffset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32034
+ const displayItems = useMemo(() => {
32035
+ if (!groupField) return placed.map((task) => ({ kind: "task", task }));
32036
+ const items = [];
32037
+ const seen = /* @__PURE__ */ new Set();
32038
+ for (const task of placed) {
32039
+ if (!seen.has(task.group)) {
32040
+ seen.add(task.group);
32041
+ items.push({ kind: "group", label: task.group || "\u2014" });
32042
+ }
32043
+ items.push({ kind: "task", task });
32044
+ }
32045
+ return items;
32046
+ }, [placed, groupField]);
32047
+ const barGeometry = useMemo(() => {
32048
+ const offset = (d) => (d.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32049
+ const map = /* @__PURE__ */ new Map();
32050
+ displayItems.forEach((item, idx) => {
32051
+ if (item.kind !== "task") return;
32052
+ const x0 = offset(item.task.start);
32053
+ const x1 = Math.max(offset(item.task.end), x0 + dayWidth / 2);
32054
+ map.set(item.task.id, { x0, x1, y: HEADER_HEIGHT + idx * ROW_HEIGHT + ROW_HEIGHT / 2 });
32055
+ });
32056
+ return map;
32057
+ }, [displayItems, axisStart, dayWidth]);
32058
+ const days = useMemo(() => {
32059
+ const out = [];
32060
+ for (let i = 0; i < totalDays; i++) out.push(new Date(axisStart.getTime() + i * DAY_MS));
32061
+ return out;
32062
+ }, [axisStart, totalDays]);
32063
+ const todayOffset = useMemo(() => {
32064
+ const today = parseDay(/* @__PURE__ */ new Date());
32065
+ if (!today || today < axisStart || today > axisEnd) return null;
32066
+ return (today.getTime() - axisStart.getTime()) / DAY_MS * dayWidth;
32067
+ }, [axisStart, axisEnd, dayWidth]);
32068
+ if (isLoading) {
32069
+ return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
32070
+ }
32071
+ if (error) {
32072
+ return /* @__PURE__ */ jsx(Box, { className: cn("p-4", className), children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
32073
+ }
32074
+ if (placed.length === 0) {
32075
+ return /* @__PURE__ */ jsx(
32076
+ EmptyState,
32077
+ {
32078
+ title: t("empty.noData"),
32079
+ className
32080
+ }
32081
+ );
32082
+ }
32083
+ return /* @__PURE__ */ jsx(
32084
+ Box,
32085
+ {
32086
+ className: cn("w-full overflow-auto rounded-md border border-border bg-card", className),
32087
+ children: /* @__PURE__ */ jsxs(Box, { className: "relative", style: { width: LABEL_WIDTH + chartWidth, minWidth: "100%" }, children: [
32088
+ /* @__PURE__ */ jsxs(HStack, { gap: "none", className: "sticky top-0 z-20 bg-card border-b border-border", style: { height: HEADER_HEIGHT }, children: [
32089
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card border-r border-border", style: { width: LABEL_WIDTH, height: HEADER_HEIGHT } }),
32090
+ /* @__PURE__ */ jsx(Box, { className: "relative", style: { width: chartWidth, height: HEADER_HEIGHT }, children: days.map((day, i) => /* @__PURE__ */ jsx(
32091
+ Box,
32092
+ {
32093
+ className: cn(
32094
+ "absolute top-0 bottom-0 border-l border-border/50 flex items-end justify-center pb-1",
32095
+ day.getDay() === 0 || day.getDay() === 6 ? "bg-muted/40" : void 0
32096
+ ),
32097
+ style: { left: i * dayWidth, width: dayWidth },
32098
+ children: dayWidth >= 20 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: day.getDate() })
32099
+ },
32100
+ i
32101
+ )) })
32102
+ ] }),
32103
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "relative", children: [
32104
+ displayItems.map(
32105
+ (item, idx) => item.kind === "group" ? /* @__PURE__ */ jsxs(
32106
+ HStack,
32107
+ {
32108
+ gap: "none",
32109
+ className: "border-b border-border bg-muted/30",
32110
+ style: { height: ROW_HEIGHT },
32111
+ children: [
32112
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-muted/30 px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(Typography, { variant: "caption", weight: "semibold", children: item.label }) }),
32113
+ /* @__PURE__ */ jsx(Box, { style: { width: chartWidth, height: ROW_HEIGHT } })
32114
+ ]
32115
+ },
32116
+ `g-${idx}`
32117
+ ) : /* @__PURE__ */ jsxs(
32118
+ HStack,
32119
+ {
32120
+ gap: "none",
32121
+ className: "border-b border-border/50",
32122
+ style: { height: ROW_HEIGHT },
32123
+ children: [
32124
+ /* @__PURE__ */ jsx(Box, { className: "sticky left-0 z-10 shrink-0 bg-card px-3 flex items-center border-r border-border", style: { width: LABEL_WIDTH, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate", children: item.task.label }) }),
32125
+ /* @__PURE__ */ jsx(Box, { className: "relative", style: { width: chartWidth, height: ROW_HEIGHT }, children: /* @__PURE__ */ jsx(
32126
+ Box,
32127
+ {
32128
+ className: cn(
32129
+ "absolute top-1/2 -translate-y-1/2 h-4 rounded-sm transition-colors",
32130
+ STATUS_BAR[item.task.status] ?? "bg-primary/80 hover:bg-primary",
32131
+ barClickEvent ? "cursor-pointer" : void 0
32132
+ ),
32133
+ style: {
32134
+ left: dayOffset(item.task.start),
32135
+ width: Math.max(dayOffset(item.task.end) - dayOffset(item.task.start), dayWidth / 2)
32136
+ },
32137
+ action: barClickEvent,
32138
+ actionPayload: { id: item.task.id }
32139
+ }
32140
+ ) })
32141
+ ]
32142
+ },
32143
+ item.task.id
32144
+ )
32145
+ ),
32146
+ links.length > 0 && /* @__PURE__ */ jsxs(
32147
+ "svg",
32148
+ {
32149
+ className: "absolute pointer-events-none",
32150
+ style: { left: LABEL_WIDTH, top: 0 },
32151
+ width: chartWidth,
32152
+ height: HEADER_HEIGHT + displayItems.length * ROW_HEIGHT,
32153
+ children: [
32154
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("marker", { id: "gantt-arrow", markerWidth: "8", markerHeight: "8", refX: "7", refY: "4", orient: "auto", children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,4 L0,8 z", fill: "var(--muted-foreground, currentColor)" }) }) }),
32155
+ links.map((link, i) => {
32156
+ const from = barGeometry.get(link.from);
32157
+ const to = barGeometry.get(link.to);
32158
+ if (!from || !to) return null;
32159
+ const midX = from.x1 + Math.max(8, (to.x0 - from.x1) / 2);
32160
+ return /* @__PURE__ */ jsx(
32161
+ "path",
32162
+ {
32163
+ d: `M ${from.x1} ${from.y} L ${midX} ${from.y} L ${midX} ${to.y} L ${to.x0} ${to.y}`,
32164
+ fill: "none",
32165
+ stroke: "var(--muted-foreground, currentColor)",
32166
+ strokeWidth: 1.5,
32167
+ markerEnd: "url(#gantt-arrow)"
32168
+ },
32169
+ i
32170
+ );
32171
+ })
32172
+ ]
32173
+ }
32174
+ ),
32175
+ showToday && todayOffset !== null && /* @__PURE__ */ jsx(
32176
+ Box,
32177
+ {
32178
+ className: "absolute top-0 bottom-0 w-0.5 bg-error/70 pointer-events-none",
32179
+ style: { left: LABEL_WIDTH + todayOffset }
32180
+ }
32181
+ )
32182
+ ] })
32183
+ ] })
32184
+ }
32185
+ );
32186
+ }
32187
+ var DAY_MS, ROW_HEIGHT, HEADER_HEIGHT, LABEL_WIDTH, STATUS_BAR;
32188
+ var init_Gantt = __esm({
32189
+ "components/core/molecules/Gantt.tsx"() {
32190
+ "use client";
32191
+ init_cn();
32192
+ init_getNestedValue();
32193
+ init_Box();
32194
+ init_Stack();
32195
+ init_Typography();
32196
+ init_LoadingState();
32197
+ init_EmptyState();
32198
+ DAY_MS = 24 * 60 * 60 * 1e3;
32199
+ ROW_HEIGHT = 36;
32200
+ HEADER_HEIGHT = 44;
32201
+ LABEL_WIDTH = 192;
32202
+ STATUS_BAR = {
32203
+ complete: "bg-success/80 hover:bg-success",
32204
+ done: "bg-success/80 hover:bg-success",
32205
+ active: "bg-primary/80 hover:bg-primary",
32206
+ "in-progress": "bg-primary/80 hover:bg-primary",
32207
+ blocked: "bg-error/80 hover:bg-error",
32208
+ error: "bg-error/80 hover:bg-error",
32209
+ "at-risk": "bg-warning/80 hover:bg-warning",
32210
+ pending: "bg-muted-foreground/50 hover:bg-muted-foreground/70"
32211
+ };
32212
+ Gantt.displayName = "Gantt";
32213
+ }
32214
+ });
31974
32215
  var RepeatableFormSection;
31975
32216
  var init_RepeatableFormSection = __esm({
31976
32217
  "components/core/molecules/RepeatableFormSection.tsx"() {
@@ -51399,6 +51640,7 @@ var init_component_registry_generated = __esm({
51399
51640
  init_GameIcon();
51400
51641
  init_GameMenu();
51401
51642
  init_GameShell();
51643
+ init_Gantt();
51402
51644
  init_GenericAppTemplate();
51403
51645
  init_GeometricPattern();
51404
51646
  init_GradientDivider();
@@ -51678,6 +51920,7 @@ var init_component_registry_generated = __esm({
51678
51920
  "GameIcon": GameIcon,
51679
51921
  "GameMenu": GameMenu,
51680
51922
  "GameShell": GameShell,
51923
+ "Gantt": Gantt,
51681
51924
  "GenericAppTemplate": GenericAppTemplate,
51682
51925
  "GeometricPattern": GeometricPattern,
51683
51926
  "GradientDivider": GradientDivider,
@@ -54745,7 +54988,7 @@ function NavStackRefBridge({ apiRef }) {
54745
54988
  }, [api, apiRef]);
54746
54989
  return null;
54747
54990
  }
54748
- function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, serverActiveTraits, children }) {
54991
+ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, serverActiveTraits, user, children }) {
54749
54992
  const bridge = useServerBridge();
54750
54993
  const activeTraitNames = useMemo(
54751
54994
  () => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
@@ -54777,12 +55020,12 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
54777
55020
  void bridge.sendEvent(name, event, withActiveTraits(payload), tick, sourceTrait);
54778
55021
  continue;
54779
55022
  }
54780
- void bridge.sendEvent(name, event, withActiveTraits(payload), void 0, void 0, locallyEmitted, results, entityByTrait).then(({ effects, meta }) => {
55023
+ void bridge.sendEvent(name, event, withActiveTraits(payload), void 0, void 0, locallyEmitted, results, entityByTrait, user ?? void 0).then(({ effects, meta }) => {
54781
55024
  recordServerResponse(name, event, { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
54782
55025
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNamesRef.current, onNavigateBack);
54783
55026
  });
54784
55027
  }
54785
- }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits]);
55028
+ }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, user]);
54786
55029
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, navigateBack: onNavigateBack, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams } : { navigate: onNavigate, navigateBack: onNavigateBack, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, callsiteCaptureChildrenByTrait, initPayload: routeParams };
54787
55030
  const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
54788
55031
  const initSentRef = useRef(false);
@@ -54824,7 +55067,17 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
54824
55067
  initSentRef.current = true;
54825
55068
  (async () => {
54826
55069
  for (const name of orbitalNames) {
54827
- const { effects, meta } = await bridge.sendEvent(name, "INIT", withActiveTraits({ ...routeParams ?? {} }));
55070
+ const { effects, meta } = await bridge.sendEvent(
55071
+ name,
55072
+ "INIT",
55073
+ withActiveTraits({ ...routeParams ?? {} }),
55074
+ void 0,
55075
+ void 0,
55076
+ void 0,
55077
+ void 0,
55078
+ void 0,
55079
+ user ?? void 0
55080
+ );
54828
55081
  recordServerResponse(name, "INIT", { ...meta, effectResults: effectResultsToTraces(meta.effectResults) });
54829
55082
  const effectTraces = [
54830
55083
  { type: "fetch", args: [], status: "executed" },
@@ -54845,7 +55098,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
54845
55098
  applyServerEffects(effects, uiSlots, onNavigate, embeddedTraits, activeTraitNamesRef.current, onNavigateBack);
54846
55099
  }
54847
55100
  })();
54848
- }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
55101
+ }, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, onNavigateBack, embeddedTraits, activeTraitNames, withActiveTraits, routeParams, user]);
54849
55102
  return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
54850
55103
  }
54851
55104
  function FitToBox({ children }) {
@@ -54872,7 +55125,7 @@ function FitToBox({ children }) {
54872
55125
  }, []);
54873
55126
  return /* @__PURE__ */ jsx("div", { ref: outerRef, className: "relative h-full w-full overflow-hidden", children: /* @__PURE__ */ jsx("div", { ref: innerRef, style: { transform: `scale(${scale})`, transformOrigin: "top left", width: "fit-content" }, children }) });
54874
55127
  }
54875
- function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData, pageName, routeParams, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence }) {
55128
+ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData, pageName, routeParams, onNavigate, onNavigateBack, onLocalFallback, localFallbackTimeoutMs, persistence, user }) {
54876
55129
  const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
54877
55130
  const allPageTraits = useMemo(() => {
54878
55131
  let base;
@@ -55037,6 +55290,7 @@ function SchemaRunner({ schema, serverUrl, transport, getAccessToken, mockData,
55037
55290
  onLocalFallback,
55038
55291
  localFallbackTimeoutMs,
55039
55292
  persistence,
55293
+ user,
55040
55294
  children: /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
55041
55295
  }
55042
55296
  )
@@ -55243,7 +55497,8 @@ function OrbPreview({
55243
55497
  onNavigateBack: handleNavigateBack,
55244
55498
  onLocalFallback: handleLocalFallback,
55245
55499
  localFallbackTimeoutMs,
55246
- persistence
55500
+ persistence,
55501
+ user
55247
55502
  }
55248
55503
  ) }) : /* @__PURE__ */ jsx(
55249
55504
  SchemaRunner,
@@ -55259,7 +55514,8 @@ function OrbPreview({
55259
55514
  onNavigateBack: handleNavigateBack,
55260
55515
  onLocalFallback: handleLocalFallback,
55261
55516
  localFallbackTimeoutMs,
55262
- persistence
55517
+ persistence,
55518
+ user
55263
55519
  }
55264
55520
  ) }) })
55265
55521
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "6.26.0",
3
+ "version": "6.28.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -118,11 +118,11 @@
118
118
  "access": "public"
119
119
  },
120
120
  "dependencies": {
121
- "@almadar/core": "^10.92.0",
122
- "@almadar/evaluator": "^2.45.0",
121
+ "@almadar/core": "^10.93.0",
122
+ "@almadar/evaluator": "^2.46.0",
123
123
  "@almadar/logger": "^1.12.0",
124
- "@almadar/runtime": "^6.79.0",
125
- "@almadar/std": "^16.217.0",
124
+ "@almadar/runtime": "^6.81.0",
125
+ "@almadar/std": "^16.219.0",
126
126
  "@almadar/syntax": "^1.17.0",
127
127
  "@dnd-kit/core": "^6.3.1",
128
128
  "@dnd-kit/sortable": "^10.0.0",