@almadar/ui 5.158.0 → 5.160.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.
@@ -14,7 +14,7 @@ import { evaluate, createMinimalContext } from '@almadar/evaluator';
14
14
  import { createContextFromBindings, interpolateValue } from '@almadar/runtime';
15
15
  import { mergeEntityFrame, isFileValue, isInlineTrait, isSecretConfigType, isRenderBindingMarker, ANIMATION_NAMES } from '@almadar/core';
16
16
  import { createPortal } from 'react-dom';
17
- import { wrapCallbackForEvent } from '@almadar/runtime/ui';
17
+ import { wrapCallbackForEvent, perfStart, perfEnd } from '@almadar/runtime/ui';
18
18
  import { Link, Outlet, useLocation } from 'react-router-dom';
19
19
  import ELK from 'elkjs/lib/elk.bundled.js';
20
20
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
@@ -6286,7 +6286,16 @@ function isPlainObject(value) {
6286
6286
  if (typeof value === "function") return false;
6287
6287
  return true;
6288
6288
  }
6289
+ function isEvaluatorResolvedData(value) {
6290
+ return evaluatorResolvedData.has(value);
6291
+ }
6292
+ function brandResolved(value) {
6293
+ if (value !== null && typeof value === "object" && !React77__default.isValidElement(value) && !(value instanceof Date)) {
6294
+ resolvedMarkerFree.add(value);
6295
+ }
6296
+ }
6289
6297
  function subtreeHasMarker(value) {
6298
+ if (resolvedMarkerFree.has(value)) return false;
6290
6299
  const cached = markerPresenceCache.get(value);
6291
6300
  if (cached !== void 0) return cached;
6292
6301
  let found = false;
@@ -6308,10 +6317,23 @@ function subtreeHasMarker(value) {
6308
6317
  }
6309
6318
  function walkValue(value, scopeTrait, entity, config, state) {
6310
6319
  if (isRenderBindingMarker(value)) {
6311
- return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
6320
+ const cached = markerResolutionCache.get(value);
6321
+ if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
6322
+ return { resolved: cached.resolved, changed: false };
6323
+ }
6324
+ const resolved = resolveMarkerExpression(value.expression, entity, config, state);
6325
+ markerResolutionCache.set(value, { entity, config, state, resolved });
6326
+ if (resolved !== null && typeof resolved === "object" && !React77__default.isValidElement(resolved) && !(resolved instanceof Date)) {
6327
+ resolvedMarkerFree.add(resolved);
6328
+ evaluatorResolvedData.add(resolved);
6329
+ }
6330
+ return { resolved, changed: true };
6312
6331
  }
6313
6332
  if (Array.isArray(value)) {
6314
- if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
6333
+ if (!subtreeHasMarker(value)) {
6334
+ brandResolved(value);
6335
+ return { resolved: value, changed: false };
6336
+ }
6315
6337
  const out = [];
6316
6338
  let changed = false;
6317
6339
  for (const item of value) {
@@ -6326,10 +6348,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
6326
6348
  out.push(resolved);
6327
6349
  if (itemChanged) changed = true;
6328
6350
  }
6351
+ brandResolved(out);
6329
6352
  return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
6330
6353
  }
6331
6354
  if (isPlainObject(value)) {
6332
- if (!subtreeHasMarker(value)) return { resolved: value, changed: false };
6355
+ if (!subtreeHasMarker(value)) {
6356
+ brandResolved(value);
6357
+ return { resolved: value, changed: false };
6358
+ }
6333
6359
  const sourceTrait = value._sourceTrait;
6334
6360
  if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
6335
6361
  return { resolved: value, changed: false };
@@ -6341,11 +6367,13 @@ function walkValue(value, scopeTrait, entity, config, state) {
6341
6367
  out[key] = resolved;
6342
6368
  if (itemChanged) changed = true;
6343
6369
  }
6370
+ brandResolved(out);
6344
6371
  return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
6345
6372
  }
6346
6373
  return { resolved: value, changed: false };
6347
6374
  }
6348
6375
  function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
6376
+ if (resolvedMarkerFree.has(props)) return props;
6349
6377
  const out = {};
6350
6378
  let changed = false;
6351
6379
  for (const [key, value] of Object.entries(props)) {
@@ -6353,13 +6381,17 @@ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
6353
6381
  out[key] = resolved;
6354
6382
  if (propChanged) changed = true;
6355
6383
  }
6384
+ brandResolved(out);
6356
6385
  return changed ? out : props;
6357
6386
  }
6358
- var markerPresenceCache;
6387
+ var markerPresenceCache, markerResolutionCache, resolvedMarkerFree, evaluatorResolvedData;
6359
6388
  var init_resolve_render_bindings = __esm({
6360
6389
  "lib/resolve-render-bindings.ts"() {
6361
6390
  "use client";
6362
6391
  markerPresenceCache = /* @__PURE__ */ new WeakMap();
6392
+ markerResolutionCache = /* @__PURE__ */ new WeakMap();
6393
+ resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
6394
+ evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
6363
6395
  }
6364
6396
  });
6365
6397
  var sizeClasses6, minWidthClasses, lookStyles2, Modal;
@@ -8445,6 +8477,10 @@ var init_ComponentPatterns = __esm({
8445
8477
  AlertPattern.displayName = "AlertPattern";
8446
8478
  }
8447
8479
  });
8480
+ var init_perf = __esm({
8481
+ "lib/perf.ts"() {
8482
+ }
8483
+ });
8448
8484
  function themeBodyFont(el) {
8449
8485
  if (typeof getComputedStyle !== "function") return "system-ui, sans-serif";
8450
8486
  const v = getComputedStyle(el).getPropertyValue("--font-family-body").trim();
@@ -8793,6 +8829,7 @@ var init_LearningCanvas = __esm({
8793
8829
  "components/learning/atoms/LearningCanvas.tsx"() {
8794
8830
  "use client";
8795
8831
  init_cn();
8832
+ init_perf();
8796
8833
  init_useEventBus();
8797
8834
  DASH_PATTERNS = { dashed: [6, 4], dotted: [2, 3] };
8798
8835
  TRACE_SERIES_COLORS = ["#2563eb", "#dc2626", "#16a34a", "#f59e0b"];
@@ -8836,6 +8873,7 @@ var init_LearningCanvas = __esm({
8836
8873
  return [...shapes, ...traceOut, ...readoutOut];
8837
8874
  }, [shapes, traces, readouts, width, height]);
8838
8875
  const draw = useCallback(() => {
8876
+ const _perfT = perfStart("learningcanvas:paint");
8839
8877
  const canvas = canvasRef.current;
8840
8878
  if (!canvas) return;
8841
8879
  const ctx = canvas.getContext("2d");
@@ -8857,6 +8895,7 @@ var init_LearningCanvas = __esm({
8857
8895
  for (const shape of derivedShapes) {
8858
8896
  if (shape.type === "text") drawShape(ctx, shape, width, height, derivedShapes);
8859
8897
  }
8898
+ perfEnd("learningcanvas:paint", _perfT);
8860
8899
  }, [width, height, backgroundColor, derivedShapes]);
8861
8900
  useEffect(() => {
8862
8901
  draw();
@@ -24187,8 +24226,8 @@ function DataGrid({
24187
24226
  }
24188
24227
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
24189
24228
  field.icon && renderIconInput(field.icon, { size: "xs", className: "text-muted-foreground" }),
24190
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
24191
- /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue(value, field.format) })
24229
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "sr-only", children: (field.label ?? fieldLabel2(field.name)) + ":" }),
24230
+ /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue(value, field.format) })
24192
24231
  ] }, field.name);
24193
24232
  }) })
24194
24233
  ] }) })
@@ -24616,7 +24655,11 @@ function DataList({
24616
24655
  Box,
24617
24656
  {
24618
24657
  className: cn(
24619
- "group flex items-center gap-4 transition-all duration-fast",
24658
+ // items-start, not items-center: a multi-line row (title + meta +
24659
+ // progress) centred its action cluster in the vertical middle, so
24660
+ // the buttons floated between the meta fields instead of anchoring
24661
+ // to the title they act on (U-DATALIST-ACTIONS-FLOAT-MID-ROW).
24662
+ "group flex items-start gap-4 transition-all duration-fast",
24620
24663
  isCompact ? "px-4 py-2" : "px-6 py-4",
24621
24664
  "hover:bg-muted/80",
24622
24665
  !isCard && !isCompact && "rounded-lg border border-transparent hover:border-border"
@@ -24647,11 +24690,19 @@ function DataList({
24647
24690
  if (value === void 0 || value === null || value === "") return null;
24648
24691
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center", children: [
24649
24692
  field.icon && renderIconInput2(field.icon, { size: "xs", className: "text-muted-foreground" }),
24650
- /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "secondary", children: [
24651
- field.label ?? fieldLabel3(field.name),
24652
- ":"
24653
- ] }),
24654
- /* @__PURE__ */ jsx(Typography, { variant: "small", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
24693
+ /* @__PURE__ */ jsxs(
24694
+ Typography,
24695
+ {
24696
+ variant: "caption",
24697
+ color: "secondary",
24698
+ className: cn(field.format !== "boolean" && "sr-only"),
24699
+ children: [
24700
+ field.label ?? fieldLabel3(field.name),
24701
+ ":"
24702
+ ]
24703
+ }
24704
+ ),
24705
+ /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: formatValue2(value, field.format, { yes: t("common.yes"), no: t("common.no") }) })
24655
24706
  ] }, field.name);
24656
24707
  }) }),
24657
24708
  progressFields.map((field) => {
@@ -24670,7 +24721,7 @@ function DataList({
24670
24721
  ]
24671
24722
  }
24672
24723
  ),
24673
- isCard && !isLast && /* @__PURE__ */ jsx(Box, { className: "mx-6 border-b border-border/40" })
24724
+ (isCard || isCompact) && !isLast && /* @__PURE__ */ jsx(Box, { className: cn("border-b border-border/40", isCompact ? "mx-4" : "mx-6") })
24674
24725
  ] }, id)
24675
24726
  );
24676
24727
  };
@@ -24680,7 +24731,13 @@ function DataList({
24680
24731
  {
24681
24732
  className: cn(
24682
24733
  isCard && "bg-card rounded-xl border border-border shadow-elevation-dialog overflow-hidden",
24683
- !isCard && gapClass,
24734
+ // `gap-*` is inert on a block container, and Box only emits a display
24735
+ // class when its `display` prop is set — so every non-card list had
24736
+ // been asking for a gap that CSS silently dropped. flex-col makes it
24737
+ // real. `compact` keeps gap-0 on purpose: it separates with the row
24738
+ // divider above instead, never both (Almadar_UI_Beauty.md 6).
24739
+ !isCard && "flex flex-col",
24740
+ !isCard && !isCompact && gapClass,
24684
24741
  listLookStyles[look],
24685
24742
  className
24686
24743
  ),
@@ -31646,6 +31703,7 @@ var init_MathCanvas = __esm({
31646
31703
  "components/learning/molecules/MathCanvas.tsx"() {
31647
31704
  "use client";
31648
31705
  init_useEventBus();
31706
+ init_perf();
31649
31707
  init_atoms();
31650
31708
  init_Stack();
31651
31709
  init_LearningCanvas();
@@ -31711,6 +31769,7 @@ var init_MathCanvas = __esm({
31711
31769
  };
31712
31770
  }, [stableKeyMap, stableKeyUpMap, eventBus]);
31713
31771
  const derivedShapes = useMemo(() => {
31772
+ const _perfT = perfStart("mathcanvas:derive");
31714
31773
  const out = [];
31715
31774
  const margin = 24;
31716
31775
  const plotW = width - margin * 2;
@@ -31954,6 +32013,7 @@ var init_MathCanvas = __esm({
31954
32013
  }
31955
32014
  }
31956
32015
  out.push(...shapes);
32016
+ perfEnd("mathcanvas:derive", _perfT);
31957
32017
  return out;
31958
32018
  }, [
31959
32019
  width,
@@ -38307,7 +38367,7 @@ var init_RichBlockEditor = __esm({
38307
38367
  {
38308
38368
  variant: "bordered",
38309
38369
  padding: "none",
38310
- className: cn("flex flex-col", className),
38370
+ className: cn("flex flex-col text-card-foreground", className),
38311
38371
  children: [
38312
38372
  enableBlocks && showToolbar && !readOnly && /* @__PURE__ */ jsx(
38313
38373
  Box,
@@ -43760,6 +43820,7 @@ var init_DetailPanel = __esm({
43760
43820
  "use client";
43761
43821
  init_atoms();
43762
43822
  init_Box();
43823
+ init_Input();
43763
43824
  init_Stack();
43764
43825
  init_SimpleGrid();
43765
43826
  init_Menu();
@@ -43775,6 +43836,7 @@ var init_DetailPanel = __esm({
43775
43836
  ReactMarkdown2 = lazy(() => import('react-markdown'));
43776
43837
  DetailPanel = ({
43777
43838
  title: propTitle,
43839
+ onTitleCommit,
43778
43840
  subtitle,
43779
43841
  status,
43780
43842
  avatar,
@@ -43796,6 +43858,7 @@ var init_DetailPanel = __esm({
43796
43858
  }) => {
43797
43859
  const eventBus = useEventBus();
43798
43860
  const { t } = useTranslate();
43861
+ const [titleDraft, setTitleDraft] = React77__default.useState(null);
43799
43862
  const isFieldDefArray = (arr) => {
43800
43863
  if (!arr || arr.length === 0) return false;
43801
43864
  const first = arr[0];
@@ -44016,6 +44079,50 @@ var init_DetailPanel = __esm({
44016
44079
  }),
44017
44080
  status && /* @__PURE__ */ jsx(Badge, { variant: status.variant ?? "default", children: status.label })
44018
44081
  ] });
44082
+ const commitTitle = () => {
44083
+ if (!onTitleCommit) return;
44084
+ const next = (titleDraft ?? "").trim();
44085
+ setTitleDraft(null);
44086
+ if (!next || next === title) return;
44087
+ onTitleCommit(next, normalizedData?.id !== void 0 ? String(normalizedData.id) : "");
44088
+ };
44089
+ const titleNode = onTitleCommit && titleDraft !== null ? /* @__PURE__ */ jsx(
44090
+ Input,
44091
+ {
44092
+ value: titleDraft,
44093
+ autoFocus: true,
44094
+ "aria-label": t("common.title"),
44095
+ className: "h-auto py-1 text-3xl font-bold tracking-tight",
44096
+ onChange: (e) => setTitleDraft(e.target.value),
44097
+ onBlur: commitTitle,
44098
+ onKeyDown: (e) => {
44099
+ if (e.key === "Enter") {
44100
+ e.preventDefault();
44101
+ commitTitle();
44102
+ } else if (e.key === "Escape") {
44103
+ e.preventDefault();
44104
+ setTitleDraft(null);
44105
+ }
44106
+ },
44107
+ "data-testid": "detail-title-input"
44108
+ }
44109
+ ) : onTitleCommit ? /* @__PURE__ */ jsx(
44110
+ Box,
44111
+ {
44112
+ role: "button",
44113
+ tabIndex: 0,
44114
+ className: "cursor-text rounded px-1 -mx-1 transition-colors hover:bg-muted/40",
44115
+ onClick: () => setTitleDraft(title ?? ""),
44116
+ onKeyDown: (e) => {
44117
+ if (e.key === "Enter" || e.key === " ") {
44118
+ e.preventDefault();
44119
+ setTitleDraft(title ?? "");
44120
+ }
44121
+ },
44122
+ "data-testid": "detail-title-editable",
44123
+ children: /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" })
44124
+ }
44125
+ ) : /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" });
44019
44126
  const content = /* @__PURE__ */ jsx(Card, { variant: "elevated", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", className: "p-6", children: [
44020
44127
  /* @__PURE__ */ jsxs(HStack, { justify: "between", align: "start", gap: "md", children: [
44021
44128
  /* @__PURE__ */ jsxs(HStack, { align: "start", gap: "sm", className: "min-w-0", children: [
@@ -44035,7 +44142,7 @@ var init_DetailPanel = __esm({
44035
44142
  avatar,
44036
44143
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "min-w-0", children: [
44037
44144
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "sm", wrap: true, children: [
44038
- /* @__PURE__ */ jsx(Typography, { variant: "h2", weight: "bold", children: title || "Details" }),
44145
+ titleNode,
44039
44146
  statusBadges
44040
44147
  ] }),
44041
44148
  subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: subtitle })
@@ -44135,16 +44242,11 @@ var init_DetailPanel = __esm({
44135
44242
  footer
44136
44243
  ] })
44137
44244
  ] }) });
44138
- return /* @__PURE__ */ jsx(
44139
- Box,
44140
- {
44141
- className: cn(
44142
- slideOver && "fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6",
44143
- className
44144
- ),
44145
- children: content
44146
- }
44147
- );
44245
+ if (!slideOver) {
44246
+ return /* @__PURE__ */ jsx(Box, { className, children: content });
44247
+ }
44248
+ const panel = /* @__PURE__ */ jsx(Box, { className: cn("fixed inset-y-0 right-0 w-full max-w-2xl bg-card shadow-lg z-50 overflow-y-auto p-6", className), children: content });
44249
+ return typeof document === "undefined" ? panel : createPortal(panel, document.body);
44148
44250
  };
44149
44251
  DetailPanel.displayName = "DetailPanel";
44150
44252
  }
@@ -44596,7 +44698,7 @@ var init_Form = __esm({
44596
44698
  });
44597
44699
  debug(
44598
44700
  "forms",
44599
- `Calculation triggered: ${calc.variableName} = ${value}`
44701
+ `Calculation triggered: ${calc.variableName} = ${String(value)}`
44600
44702
  );
44601
44703
  }
44602
44704
  });
@@ -51076,6 +51178,7 @@ function isPlainConfigObject(value) {
51076
51178
  return proto === Object.prototype || proto === null;
51077
51179
  }
51078
51180
  function subtreeHasTraitRef(value) {
51181
+ if (isEvaluatorResolvedData(value)) return false;
51079
51182
  const cached = traitRefPresenceCache.get(value);
51080
51183
  if (cached !== void 0) return cached;
51081
51184
  let found = false;
@@ -51148,6 +51251,10 @@ function renderPatternProps(props, onDismiss, propsSchema) {
51148
51251
  };
51149
51252
  rendered[key] = /* @__PURE__ */ jsx(SlotContentRenderer, { content: childContent, onDismiss });
51150
51253
  } else if (Array.isArray(value)) {
51254
+ if (!isEvaluatorResolvedData(value) && value.some((el) => isPatternConfig(el))) ; else if (!subtreeHasTraitRef(value)) {
51255
+ rendered[key] = value;
51256
+ continue;
51257
+ }
51151
51258
  const isDataArray = propsSchema?.[key]?.items?.types?.includes("object") ?? false;
51152
51259
  rendered[key] = value.map((item, i) => {
51153
51260
  const el = item;
@@ -52599,6 +52706,88 @@ function useDeepAgentGeneration() {
52599
52706
 
52600
52707
  // hooks/index.ts
52601
52708
  init_useEventBus();
52709
+ function expressionEqual(a, b) {
52710
+ if (Object.is(a, b)) return true;
52711
+ if (Array.isArray(a) && Array.isArray(b)) {
52712
+ if (a.length !== b.length) return false;
52713
+ for (let i = 0; i < a.length; i++) {
52714
+ if (!expressionEqual(a[i], b[i])) return false;
52715
+ }
52716
+ return true;
52717
+ }
52718
+ if (a !== null && b !== null && typeof a === "object" && typeof b === "object" && !Array.isArray(a) && !Array.isArray(b) && !(a instanceof Date) && !(b instanceof Date)) {
52719
+ const aKeys = Object.keys(a);
52720
+ const bKeys = Object.keys(b);
52721
+ if (aKeys.length !== bKeys.length) return false;
52722
+ for (const key of aKeys) {
52723
+ if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
52724
+ if (!expressionEqual(
52725
+ a[key],
52726
+ b[key]
52727
+ )) return false;
52728
+ }
52729
+ return true;
52730
+ }
52731
+ return false;
52732
+ }
52733
+ function isPlainSlotObject(value) {
52734
+ if (value === null || value === void 0 || typeof value !== "object") return false;
52735
+ if (Array.isArray(value)) return false;
52736
+ if (React77__default.isValidElement(value)) return false;
52737
+ if (value instanceof Date) return false;
52738
+ if (isRenderBindingMarker(value)) return false;
52739
+ return true;
52740
+ }
52741
+ function shareValue(prev, next) {
52742
+ if (Object.is(prev, next)) return { value: prev, equal: true };
52743
+ const prevMarker = isRenderBindingMarker(prev) ? prev : void 0;
52744
+ const nextMarker = isRenderBindingMarker(next) ? next : void 0;
52745
+ if (prevMarker !== void 0 || nextMarker !== void 0) {
52746
+ if (prevMarker !== void 0 && nextMarker !== void 0 && expressionEqual(prevMarker.expression, nextMarker.expression)) {
52747
+ return { value: prev, equal: true };
52748
+ }
52749
+ return { value: next, equal: false };
52750
+ }
52751
+ if (prev instanceof Date || next instanceof Date) {
52752
+ return prev instanceof Date && next instanceof Date && prev.getTime() === next.getTime() ? { value: prev, equal: true } : { value: next, equal: false };
52753
+ }
52754
+ if (typeof prev === "function" || typeof next === "function") return { value: next, equal: false };
52755
+ if (React77__default.isValidElement(prev) || React77__default.isValidElement(next)) return { value: next, equal: false };
52756
+ if (Array.isArray(prev) && Array.isArray(next)) {
52757
+ let equal = prev.length === next.length;
52758
+ const out = new Array(next.length);
52759
+ for (let i = 0; i < next.length; i++) {
52760
+ const child = shareValue(prev[i], next[i]);
52761
+ out[i] = child.value;
52762
+ if (!child.equal) equal = false;
52763
+ }
52764
+ return equal ? { value: prev, equal: true } : { value: out, equal: false };
52765
+ }
52766
+ if (isPlainSlotObject(prev) && isPlainSlotObject(next)) {
52767
+ const prevKeys = Object.keys(prev);
52768
+ const nextKeys = Object.keys(next);
52769
+ let equal = prevKeys.length === nextKeys.length;
52770
+ const out = {};
52771
+ for (const key of nextKeys) {
52772
+ if (!Object.prototype.hasOwnProperty.call(prev, key)) {
52773
+ equal = false;
52774
+ out[key] = next[key];
52775
+ continue;
52776
+ }
52777
+ const child = shareValue(prev[key], next[key]);
52778
+ out[key] = child.value;
52779
+ if (!child.equal) equal = false;
52780
+ }
52781
+ return equal ? { value: prev, equal: true } : { value: out, equal: false };
52782
+ }
52783
+ return { value: next, equal: false };
52784
+ }
52785
+ function reconcileSlotProps(prev, next) {
52786
+ const result = shareValue(prev, next);
52787
+ return { value: result.value, equal: result.equal };
52788
+ }
52789
+
52790
+ // hooks/useUISlots.ts
52602
52791
  var log17 = createLogger("almadar:ui:ui-slots");
52603
52792
  var DEFAULT_SOURCE_KEY = "__default__";
52604
52793
  var MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
@@ -52753,6 +52942,14 @@ function useUISlotManager() {
52753
52942
  });
52754
52943
  return prev;
52755
52944
  }
52945
+ if (existing && existing.priority === content.priority && existing.pattern === content.pattern && existing.animation === content.animation && existing.transitionEvent === content.transitionEvent && existing.fromState === content.fromState && existing.entity === content.entity && existing.nodeId === content.nodeId && existing.autoDismissAt === void 0 && content.autoDismissAt === void 0 && existing.onDismiss === void 0 === (content.onDismiss === void 0)) {
52946
+ const reconciled = reconcileSlotProps(existing.props, content.props);
52947
+ if (reconciled.equal) {
52948
+ log17.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
52949
+ return prev;
52950
+ }
52951
+ content.props = reconciled.value;
52952
+ }
52756
52953
  const nextSources = {
52757
52954
  ...slotSources,
52758
52955
  [sourceKey]: content
@@ -53100,6 +53297,7 @@ var en_default = {
53100
53297
  "common.confirm": "Are you sure?",
53101
53298
  "common.create": "Create",
53102
53299
  "common.edit": "Edit",
53300
+ "common.title": "Title",
53103
53301
  "common.view": "View",
53104
53302
  "common.add": "Add",
53105
53303
  "common.remove": "Remove",