@almadar/ui 6.53.0 → 6.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/Typography-CFI7JUVE.js +5 -0
  2. package/dist/{UISlotRenderer-JT34I3O7.js → UISlotRenderer-QUEG6WFM.js} +5 -5
  3. package/dist/avl/index.cjs +578 -262
  4. package/dist/avl/index.js +28 -19
  5. package/dist/{avl-3d-context-MAt_NuU9.d.ts → avl-3d-context-BpBKZIbc.d.ts} +1 -0
  6. package/dist/{chunk-DQTV6QVS.js → chunk-4HC5HRHB.js} +53 -2
  7. package/dist/{chunk-GMDMOYXD.js → chunk-4UP6BZ4R.js} +1 -1
  8. package/dist/{chunk-CBIJP5PL.js → chunk-FJDS4SVD.js} +3 -3
  9. package/dist/{chunk-4OZDHCZV.js → chunk-MCKFWPT2.js} +1 -1
  10. package/dist/{chunk-UGHAADU5.js → chunk-N2V4LHFQ.js} +4 -1
  11. package/dist/{chunk-3EF5SDIJ.js → chunk-U2FGMHQP.js} +306 -174
  12. package/dist/{chunk-IKULQIDX.js → chunk-U3CGKPOK.js} +252 -91
  13. package/dist/{chunk-7LM6I3NA.js → chunk-Z5IYJU44.js} +1 -0
  14. package/dist/{chunk-WPNM2KC6.js → chunk-Z7JWXIRE.js} +2 -2
  15. package/dist/components/index.cjs +312 -170
  16. package/dist/components/index.d.ts +5 -1
  17. package/dist/components/index.js +11 -12
  18. package/dist/context/index.cjs +2 -0
  19. package/dist/context/index.js +2 -0
  20. package/dist/hooks/index.cjs +9 -1
  21. package/dist/hooks/index.d.ts +10 -1
  22. package/dist/hooks/index.js +3 -4
  23. package/dist/lib/drawable/three/index.cjs +5 -1
  24. package/dist/lib/drawable/three/index.d.ts +2 -2
  25. package/dist/lib/drawable/three/index.js +6 -6
  26. package/dist/lib/index.cjs +4 -1
  27. package/dist/lib/index.js +2 -2
  28. package/dist/locales/index.cjs +12 -3
  29. package/dist/locales/index.js +9 -3
  30. package/dist/providers/index.cjs +307 -170
  31. package/dist/providers/index.d.ts +1 -1
  32. package/dist/providers/index.js +5 -5
  33. package/dist/runtime/index.cjs +3850 -3523
  34. package/dist/runtime/index.d.ts +22 -4
  35. package/dist/runtime/index.js +13 -10
  36. package/dist/ssr/index.cjs +5 -2
  37. package/dist/ssr/index.js +5 -2
  38. package/locales/ar.json +4 -1
  39. package/locales/en.json +4 -1
  40. package/locales/sl.json +4 -1
  41. package/package.json +7 -6
  42. package/scripts/audit-tailwind-safelist.ts +21 -1
  43. package/tailwind-preset.cjs +15 -6
  44. package/themes/_fonts.css +6 -4
  45. package/themes/_presets.css +2 -0
  46. package/themes/almadar-heritage.css +373 -0
  47. package/themes/orb.css +373 -0
  48. package/dist/Typography-JGSDH4JP.js +0 -5
  49. package/dist/chunk-GODZKHAL.js +0 -51
@@ -1,12 +1,12 @@
1
- import { pressableProps, Box, HStack, isAtlasAsset, getAtlas, subRectFor, VStack, createConfettiParticles, CONFETTI_BURST_KEYFRAMES, getStateRole, AVL_INK, AVL_FONT, AVL_STROKE, avlTint, collectDrawnItems, buildHitIndex, resolveAssetSource, blit, withPreviewPosition, hitTestSprites, Stack, DrawableRegistryContext, traitLevelFromTrait, rowOpenControlProps, STRETCHED_ABOVE, STRETCHED_CONTROL, resolveThemeColor, THEME_SERIES, STATE_COLORS, effectCategoryOf, EFFECT_CATEGORY_COLORS, expandFxLayer, paintSkinnedMesh, isValidScenePos, isAnimatedGroup, applyMeshAnimation, paintShape, spriteRect, getOrLoadImage, asEffectOperator, CONNECTION_COLORS, DrawSkinnedMesh, DrawShape, DrawMesh, DrawGroup, DrawFxLayer, isAnimatedShape, spriteAssetState, getImageStatus, atlasUrlOf, atlasFailed, isSpriteSheetAtlas, fxHash01, SPRITE_FALLBACK_FILL, SPRITE_FALLBACK_STROKE } from './chunk-7LM6I3NA.js';
2
- import { INLINE_TEXT_ATTR, Typography } from './chunk-GMDMOYXD.js';
1
+ import { pressableProps, Box, HStack, isAtlasAsset, getAtlas, subRectFor, VStack, createConfettiParticles, CONFETTI_BURST_KEYFRAMES, getStateRole, AVL_INK, AVL_FONT, AVL_STROKE, avlTint, collectDrawnItems, buildHitIndex, resolveAssetSource, blit, withPreviewPosition, hitTestSprites, Stack, DrawableRegistryContext, traitLevelFromTrait, rowOpenControlProps, STRETCHED_ABOVE, STRETCHED_CONTROL, resolveThemeColor, THEME_SERIES, STATE_COLORS, effectCategoryOf, EFFECT_CATEGORY_COLORS, expandFxLayer, paintSkinnedMesh, isValidScenePos, isAnimatedGroup, applyMeshAnimation, paintShape, spriteRect, getOrLoadImage, asEffectOperator, CONNECTION_COLORS, DrawSkinnedMesh, DrawShape, DrawMesh, DrawGroup, DrawFxLayer, isAnimatedShape, spriteAssetState, getImageStatus, atlasUrlOf, atlasFailed, isSpriteSheetAtlas, fxHash01, SPRITE_FALLBACK_FILL, SPRITE_FALLBACK_STROKE } from './chunk-Z5IYJU44.js';
2
+ import { INLINE_TEXT_ATTR, Typography } from './chunk-4UP6BZ4R.js';
3
3
  import { usePendingAction, useMediaQuery, useInfiniteScroll, usePrefersReducedMotion, useCanvasGestures, useSwipeGesture, useLongPress, useAuthContext, useQuerySingleton, usePullToRefresh, useDragReorder, usePendingScopeValue, PendingScopeContext, useScopeHasPending, usePendingRows, useDraggable, useDropZone } from './chunk-JRW33U35.js';
4
4
  import { useTapReveal } from './chunk-XJTHMW4G.js';
5
5
  import { useEventBus, useEventListener } from './chunk-6EV3OEBQ.js';
6
6
  import { computeLineDiff, isEditorMotion, applyMotion, isEditorOperator, motionRange, applyOperator, usePresence, isMotionEnabled, gearTeethPath, perfStart, perfEnd, parseMarkdownWithCodeBlocks, getNestedValue, parseContentSegments, resolveImageUrl, debugGroup, debug, debugGroupEnd, isDebugEnabled, isDebugEnabled2, onDebugToggle, Presence, asEnterAnimation, slotPlaysDefaultEnter, useSlotEnterRestart, ENTER_SLOT_CLASS, enterClassName, subscribeToTraitChanges, subscribeToTickChanges, subscribeToGuardChanges, subscribeToDebugEvents, getEntitySnapshot, getDebugEvents, getGuardHistory, getAllTicks, getAllTraits } from './chunk-KQXXO42S.js';
7
7
  import { updateAssetStatus, bindCanvasCapture, bindLastDrawables, resolveKeyMapEvent, subscribeToVerification, getSummary, getBridgeHealth, getTransitions, getAllChecks } from './chunk-O7OLVVBR.js';
8
8
  import { cn, domPassthrough } from './chunk-64WACXM7.js';
9
- import { formatValue, sortRows, formatDate, toDateTimeInputValue, toDateInputValue } from './chunk-4OZDHCZV.js';
9
+ import { formatValue, sortRows, formatDate, toDateTimeInputValue, toDateInputValue } from './chunk-MCKFWPT2.js';
10
10
  import { isPortalSlot } from './chunk-PEST66PN.js';
11
11
  import { __publicField } from './chunk-QPXIAUJD.js';
12
12
  import * as React86 from 'react';
@@ -20,7 +20,7 @@ import { useTheme, useThemeScope, useUISlots } from '@almadar/ui/context';
20
20
  import * as LucideIcons2 from 'lucide-react';
21
21
  import { Loader2, X, Code, FileText, WrapText, Check, Copy, ChevronDown, ChevronRight, Lightbulb, CheckCircle, GitBranch, Pencil, Eye, Plus, ChevronLeft, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, HelpCircle, AlertCircle, Circle, Clock, CheckCircle2, ArrowLeft, Bold, Italic, Underline, Strikethrough, Heading1, Heading2, Heading3, List, ListOrdered, Quote, Link as Link$1, Image as Image$1, Minus, ZoomOut, ZoomIn, Download, Printer, Search, DollarSign, Menu as Menu$1, Upload, PauseCircle, Eraser, TrendingUp, TrendingDown, ArrowRight, Trash } from 'lucide-react';
22
22
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
- import { useTranslate, useFormatContext } from '@almadar/ui/hooks';
23
+ import { useTranslate, useFormatContext, useRenderI18n } from '@almadar/ui/hooks';
24
24
  import { createPortal } from 'react-dom';
25
25
  import { createLogger } from '@almadar/logger';
26
26
  import { evaluate, createMinimalContext, createChildContext } from '@almadar/evaluator';
@@ -33,6 +33,7 @@ import rehypeKatex from 'rehype-katex';
33
33
  import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light.js';
34
34
  import createHighlightElement from 'react-syntax-highlighter/dist/esm/create-element.js';
35
35
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
36
+ import light from 'react-syntax-highlighter/dist/esm/styles/prism/vs.js';
36
37
  import { orbLanguage, loloLanguage, ORB_COLORS, translateLolo, translateOrb } from '@almadar/syntax';
37
38
  import { coreTables } from '@almadar/core/i18n';
38
39
  import langJson from 'react-syntax-highlighter/dist/esm/languages/prism/json.js';
@@ -89,12 +90,13 @@ import emojilib from 'emojilib';
89
90
  import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
90
91
  import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
91
92
 
92
- function resolveMarkerExpression(expression, entity, config, state) {
93
+ function resolveMarkerExpression(expression, entity, config, state, i18n) {
93
94
  const ctx = createContextFromBindings({
94
95
  entity,
95
96
  payload: {},
96
97
  state,
97
- ...config !== void 0 ? { config } : {}
98
+ ...config !== void 0 ? { config } : {},
99
+ ...i18n !== void 0 ? { locale: i18n.locale, messages: i18n.messages } : {}
98
100
  });
99
101
  return interpolateValue(expression, ctx);
100
102
  }
@@ -109,9 +111,9 @@ function isPlainObject(value) {
109
111
  var markerPresenceCache = /* @__PURE__ */ new WeakMap();
110
112
  var markerResolutionCache = /* @__PURE__ */ new WeakMap();
111
113
  var containerResolutionCache = /* @__PURE__ */ new WeakMap();
112
- function cachedContainer(value, scopeTrait, entity, config, state) {
114
+ function cachedContainer(value, scopeTrait, entity, config, state, i18n) {
113
115
  const hit = containerResolutionCache.get(value);
114
- return hit !== void 0 && hit.entity === entity && hit.config === config && hit.state === state && hit.scopeTrait === scopeTrait ? hit.resolved : void 0;
116
+ return hit !== void 0 && hit.entity === entity && hit.config === config && hit.state === state && hit.i18n === i18n && hit.scopeTrait === scopeTrait ? hit.resolved : void 0;
115
117
  }
116
118
  var resolvedMarkerFree = /* @__PURE__ */ new WeakSet();
117
119
  var evaluatorResolvedData = /* @__PURE__ */ new WeakSet();
@@ -144,14 +146,14 @@ function subtreeHasMarker(value) {
144
146
  markerPresenceCache.set(value, found);
145
147
  return found;
146
148
  }
147
- function walkValue(value, scopeTrait, entity, config, state) {
149
+ function walkValue(value, scopeTrait, entity, config, state, i18n) {
148
150
  if (isRenderBindingMarker(value)) {
149
151
  const cached = markerResolutionCache.get(value);
150
- if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state) {
152
+ if (cached !== void 0 && cached.entity === entity && cached.config === config && cached.state === state && cached.i18n === i18n) {
151
153
  return { resolved: cached.resolved, changed: true };
152
154
  }
153
- const resolved = resolveMarkerExpression(value.expression, entity, config, state);
154
- markerResolutionCache.set(value, { entity, config, state, resolved });
155
+ const resolved = resolveMarkerExpression(value.expression, entity, config, state, i18n);
156
+ markerResolutionCache.set(value, { entity, config, state, i18n, resolved });
155
157
  if (resolved !== null && typeof resolved === "object" && !React86__default.isValidElement(resolved) && !(resolved instanceof Date)) {
156
158
  resolvedMarkerFree.add(resolved);
157
159
  evaluatorResolvedData.add(resolved);
@@ -163,14 +165,14 @@ function walkValue(value, scopeTrait, entity, config, state) {
163
165
  brandResolved(value);
164
166
  return { resolved: value, changed: false };
165
167
  }
166
- const cachedArray = cachedContainer(value, scopeTrait, entity, config, state);
168
+ const cachedArray = cachedContainer(value, scopeTrait, entity, config, state, i18n);
167
169
  if (cachedArray !== void 0) return { resolved: cachedArray, changed: true };
168
170
  const out = [];
169
171
  let changed = false;
170
172
  for (const item of value) {
171
173
  const element = item;
172
174
  const wasMarker = isRenderBindingMarker(element);
173
- const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
175
+ const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state, i18n);
174
176
  if (wasMarker && Array.isArray(resolved)) {
175
177
  out.push(...resolved);
176
178
  changed = true;
@@ -181,7 +183,7 @@ function walkValue(value, scopeTrait, entity, config, state) {
181
183
  }
182
184
  brandResolved(out);
183
185
  if (!changed) return { resolved: value, changed: false };
184
- containerResolutionCache.set(value, { entity, config, state, scopeTrait, resolved: out });
186
+ containerResolutionCache.set(value, { entity, config, state, i18n, scopeTrait, resolved: out });
185
187
  return { resolved: out, changed: true };
186
188
  }
187
189
  if (isPlainObject(value)) {
@@ -193,37 +195,37 @@ function walkValue(value, scopeTrait, entity, config, state) {
193
195
  if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
194
196
  return { resolved: value, changed: false };
195
197
  }
196
- const cachedObject = cachedContainer(value, scopeTrait, entity, config, state);
198
+ const cachedObject = cachedContainer(value, scopeTrait, entity, config, state, i18n);
197
199
  if (cachedObject !== void 0) return { resolved: cachedObject, changed: true };
198
200
  const out = {};
199
201
  let changed = false;
200
202
  for (const [key, item] of Object.entries(value)) {
201
- const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
203
+ const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state, i18n);
202
204
  out[key] = resolved;
203
205
  if (itemChanged) changed = true;
204
206
  }
205
207
  brandResolved(out);
206
208
  if (!changed) return { resolved: value, changed: false };
207
- containerResolutionCache.set(value, { entity, config, state, scopeTrait, resolved: out });
209
+ containerResolutionCache.set(value, { entity, config, state, i18n, scopeTrait, resolved: out });
208
210
  return { resolved: out, changed: true };
209
211
  }
210
212
  return { resolved: value, changed: false };
211
213
  }
212
- function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
214
+ function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state, i18n) {
213
215
  if (props === null || typeof props !== "object") return props;
214
216
  if (resolvedMarkerFree.has(props)) return props;
215
- const cached = cachedContainer(props, scopeTrait, entity, config, state);
217
+ const cached = cachedContainer(props, scopeTrait, entity, config, state, i18n);
216
218
  if (cached !== void 0) return cached;
217
219
  const out = {};
218
220
  let changed = false;
219
221
  for (const [key, value] of Object.entries(props)) {
220
- const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
222
+ const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state, i18n);
221
223
  out[key] = resolved;
222
224
  if (propChanged) changed = true;
223
225
  }
224
226
  brandResolved(out);
225
227
  if (!changed) return props;
226
- containerResolutionCache.set(props, { entity, config, state, scopeTrait, resolved: out });
228
+ containerResolutionCache.set(props, { entity, config, state, i18n, scopeTrait, resolved: out });
227
229
  return out;
228
230
  }
229
231
  var DEFAULT_FAMILY = "lucide";
@@ -800,7 +802,7 @@ var Button = React86__default.forwardRef(
800
802
  const testId = dataTestId ?? (action ? `action-${action}` : void 0);
801
803
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
802
804
  busy && /* @__PURE__ */ jsx("span", { className: "almadar-busy-indicator absolute inset-0 flex items-center justify-center", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Loader2, { className: "h-icon-default w-icon-default animate-spin" }) }),
803
- /* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center justify-center gap-2", busy && "almadar-busy-content"), children: [
805
+ /* @__PURE__ */ jsxs("span", { className: cn("inline-flex flex-1 min-w-0 items-center [justify-content:inherit] gap-2", busy && "almadar-busy-content"), children: [
804
806
  resolvedLeftIcon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: resolvedLeftIcon }),
805
807
  (Array.isArray(children) ? children.length > 0 : Boolean(children)) ? children : label ? /* @__PURE__ */ jsx("span", { ...{ [INLINE_TEXT_ATTR]: "label" }, children: label }) : label,
806
808
  resolvedRightIcon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: resolvedRightIcon })
@@ -6840,7 +6842,7 @@ function renderVariant(variant, rows2, columns, fields, className) {
6840
6842
  }
6841
6843
  Skeleton.displayName = "Skeleton";
6842
6844
  var LazySlotContentRenderer = lazy(
6843
- () => import('./UISlotRenderer-JT34I3O7.js').then((m) => ({
6845
+ () => import('./UISlotRenderer-QUEG6WFM.js').then((m) => ({
6844
6846
  default: m.SlotContentRenderer
6845
6847
  }))
6846
6848
  );
@@ -12578,6 +12580,28 @@ var Tabs = ({
12578
12580
  const uid = useId();
12579
12581
  const tabId = (id) => `${uid}-tab-${id}`;
12580
12582
  const panelId = (id) => `${uid}-panel-${id}`;
12583
+ const laneRef = useRef(null);
12584
+ const [hidden, setHidden] = useState({ start: false, end: false });
12585
+ const measure = useCallback(() => {
12586
+ const lane = laneRef.current;
12587
+ if (!lane || orientation !== "horizontal") return;
12588
+ const max = lane.scrollWidth - lane.clientWidth;
12589
+ const start = max > 1 && lane.scrollLeft > 1;
12590
+ const end = max > 1 && lane.scrollLeft < max - 1;
12591
+ setHidden((prev) => prev.start === start && prev.end === end ? prev : { start, end });
12592
+ }, [orientation]);
12593
+ useLayoutEffect(() => {
12594
+ measure();
12595
+ const lane = laneRef.current;
12596
+ if (!lane || typeof ResizeObserver === "undefined") return void 0;
12597
+ const observer2 = new ResizeObserver(measure);
12598
+ observer2.observe(lane);
12599
+ return () => observer2.disconnect();
12600
+ }, [measure, rawItems.length]);
12601
+ const scrollLane = (direction) => {
12602
+ const lane = laneRef.current;
12603
+ if (lane) lane.scrollBy({ left: direction * lane.clientWidth * 0.8, behavior: "smooth" });
12604
+ };
12581
12605
  const handleTabChange = (tabId2, tabEvent) => {
12582
12606
  if (controlledActiveTab === void 0) {
12583
12607
  setInternalActiveTab(tabId2);
@@ -12634,62 +12658,97 @@ var Tabs = ({
12634
12658
  "data-[active=true]:border-primary"
12635
12659
  ].join(" ")
12636
12660
  };
12637
- return /* @__PURE__ */ jsxs(Box, { ...domPassthrough(rest), className: cn("w-full", orientation === "vertical" && "flex flex-row", className), children: [
12638
- /* @__PURE__ */ jsx(
12639
- Box,
12640
- {
12641
- role: "tablist",
12642
- "aria-orientation": orientation,
12643
- className: cn(
12644
- "flex",
12645
- // Horizontal tab strip becomes a horizontally-scrollable lane
12646
- // below its container width — phones with many tabs scroll
12647
- // instead of clipping. `snap-x` snaps to each tab; the
12648
- // scrollbar is hidden for a cleaner affordance (the swipe
12649
- // gesture is the discoverability cue).
12650
- orientation === "horizontal" ? "flex-row border-b-[length:var(--border-width)] border-border overflow-x-auto snap-x snap-mandatory [&::-webkit-scrollbar]:hidden" : "flex-col border-r-[length:var(--border-width)] border-border",
12651
- variant === "pills" && "gap-1 p-1 bg-muted border-0 rounded-interactive",
12652
- variant === "underline" && orientation === "vertical" && "border-b-0"
12653
- ),
12654
- children: safeItems.map((item, index) => {
12655
- const isActive = item.id === activeTab;
12656
- const isDisabled = item.disabled;
12657
- return /* @__PURE__ */ jsxs(
12658
- Box,
12659
- {
12660
- as: "button",
12661
- ref: (el) => {
12662
- tabRefs.current[item.id] = el;
12663
- },
12664
- id: tabId(item.id),
12665
- role: "tab",
12666
- "aria-selected": isActive,
12667
- "aria-controls": isActive ? panelId(item.id) : void 0,
12668
- "aria-disabled": isDisabled,
12669
- tabIndex: isActive ? 0 : -1,
12670
- onClick: () => !isDisabled && handleTabChange(item.id, item.event),
12671
- onKeyDown: (e) => handleKeyDown(e, index),
12672
- "data-active": isActive,
12673
- "data-testid": `tab-${item.id}`,
12674
- className: cn(
12675
- "flex items-center gap-2 px-4 py-2 text-sm font-medium transition-colors whitespace-nowrap",
12676
- orientation === "horizontal" && "snap-start shrink-0",
12677
- "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
12678
- isDisabled && "opacity-50 cursor-not-allowed",
12679
- variantClasses2[variant],
12680
- isActive ? variant === "pills" ? "text-primary-foreground" : "text-foreground" : "text-muted-foreground hover:text-foreground"
12681
- ),
12682
- children: [
12683
- item.iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: item.iconAsset.url, alt: item.iconAsset.name ?? item.iconAsset.category ?? "", width: 16, height: 16, style: { imageRendering: "pixelated", objectFit: "contain", width: 16, height: 16 }, className: "flex-shrink-0" }) : item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
12684
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "!text-inherit", children: item.label }),
12685
- item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
12686
- ]
12661
+ const tablist = /* @__PURE__ */ jsx(
12662
+ Box,
12663
+ {
12664
+ ref: laneRef,
12665
+ role: "tablist",
12666
+ "aria-orientation": orientation,
12667
+ onScroll: measure,
12668
+ "data-scroll-affordance": hidden.start || hidden.end ? "true" : void 0,
12669
+ className: cn(
12670
+ "flex",
12671
+ // Horizontal tab strip becomes a horizontally-scrollable lane
12672
+ // below its container width — phones with many tabs scroll
12673
+ // instead of clipping. `snap-x` snaps to each tab; the
12674
+ // scrollbar is hidden — the edge chevrons are the affordance.
12675
+ orientation === "horizontal" ? "flex-row border-b-[length:var(--border-width)] border-border overflow-x-auto snap-x snap-mandatory [&::-webkit-scrollbar]:hidden" : "flex-col border-r-[length:var(--border-width)] border-border",
12676
+ variant === "pills" && "gap-1 p-1 bg-muted border-0 rounded-interactive",
12677
+ variant === "underline" && orientation === "vertical" && "border-b-0"
12678
+ ),
12679
+ children: safeItems.map((item, index) => {
12680
+ const isActive = item.id === activeTab;
12681
+ const isDisabled = item.disabled;
12682
+ return /* @__PURE__ */ jsxs(
12683
+ Box,
12684
+ {
12685
+ as: "button",
12686
+ ref: (el) => {
12687
+ tabRefs.current[item.id] = el;
12687
12688
  },
12688
- item.id
12689
- );
12690
- })
12691
- }
12692
- ),
12689
+ id: tabId(item.id),
12690
+ role: "tab",
12691
+ "aria-selected": isActive,
12692
+ "aria-controls": isActive ? panelId(item.id) : void 0,
12693
+ "aria-disabled": isDisabled,
12694
+ tabIndex: isActive ? 0 : -1,
12695
+ onClick: () => !isDisabled && handleTabChange(item.id, item.event),
12696
+ onKeyDown: (e) => handleKeyDown(e, index),
12697
+ "data-active": isActive,
12698
+ "data-testid": `tab-${item.id}`,
12699
+ className: cn(
12700
+ "flex items-center gap-2 px-4 py-2 text-sm font-medium transition-colors whitespace-nowrap",
12701
+ orientation === "horizontal" && "snap-start shrink-0",
12702
+ "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
12703
+ isDisabled && "opacity-50 cursor-not-allowed",
12704
+ variantClasses2[variant],
12705
+ isActive ? variant === "pills" ? "text-primary-foreground" : "text-foreground" : "text-muted-foreground hover:text-foreground"
12706
+ ),
12707
+ children: [
12708
+ item.iconAsset?.url ? /* @__PURE__ */ jsx("img", { src: item.iconAsset.url, alt: item.iconAsset.name ?? item.iconAsset.category ?? "", width: 16, height: 16, style: { imageRendering: "pixelated", objectFit: "contain", width: 16, height: 16 }, className: "flex-shrink-0" }) : item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
12709
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "medium", className: "!text-inherit", children: item.label }),
12710
+ item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
12711
+ ]
12712
+ },
12713
+ item.id
12714
+ );
12715
+ })
12716
+ }
12717
+ );
12718
+ return /* @__PURE__ */ jsxs(Box, { ...domPassthrough(rest), className: cn("w-full", orientation === "vertical" && "flex flex-row", className), children: [
12719
+ orientation === "horizontal" ? /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
12720
+ tablist,
12721
+ hidden.start && /* @__PURE__ */ jsxs(Fragment, { children: [
12722
+ /* @__PURE__ */ jsx(Box, { className: "pointer-events-none absolute inset-y-0 start-0 w-10 bg-gradient-to-r from-[var(--color-background)] to-transparent rtl:bg-gradient-to-l" }),
12723
+ /* @__PURE__ */ jsx(
12724
+ Button,
12725
+ {
12726
+ variant: "ghost",
12727
+ size: "sm",
12728
+ leftIcon: "chevron-left",
12729
+ "aria-label": t("tabs.scrollStart"),
12730
+ "data-testid": "tabs-scroll-start",
12731
+ className: "absolute start-0 top-1/2 -translate-y-1/2 px-1 rtl:rotate-180",
12732
+ onClick: () => scrollLane(-1)
12733
+ }
12734
+ )
12735
+ ] }),
12736
+ hidden.end && /* @__PURE__ */ jsxs(Fragment, { children: [
12737
+ /* @__PURE__ */ jsx(Box, { className: "pointer-events-none absolute inset-y-0 end-0 w-10 bg-gradient-to-l from-[var(--color-background)] to-transparent rtl:bg-gradient-to-r" }),
12738
+ /* @__PURE__ */ jsx(
12739
+ Button,
12740
+ {
12741
+ variant: "ghost",
12742
+ size: "sm",
12743
+ leftIcon: "chevron-right",
12744
+ "aria-label": t("tabs.scrollEnd"),
12745
+ "data-testid": "tabs-scroll-end",
12746
+ className: "absolute end-0 top-1/2 -translate-y-1/2 px-1 rtl:rotate-180",
12747
+ onClick: () => scrollLane(1)
12748
+ }
12749
+ )
12750
+ ] })
12751
+ ] }) : tablist,
12693
12752
  activeTabContent !== void 0 && activeTabContent !== null && /* @__PURE__ */ jsx(
12694
12753
  Box,
12695
12754
  {
@@ -13399,48 +13458,57 @@ async function loadPrismLanguage(lang) {
13399
13458
  dynamicallyLoaded.add(lang);
13400
13459
  }
13401
13460
  }
13402
- var orbStyleOverrides = {
13403
- "orb-binding": { color: ORB_COLORS.dark.binding, fontWeight: "bold" },
13404
- "orb-effect": { color: ORB_COLORS.dark.effect, fontWeight: "bold" },
13405
- "orb-event": { color: ORB_COLORS.dark.event },
13406
- "orb-slot": { color: ORB_COLORS.dark.uiSlot },
13407
- "orb-structural": { color: ORB_COLORS.dark.structural },
13408
- "orb-field-type": { color: ORB_COLORS.dark.fieldType },
13409
- "orb-persistence": { color: ORB_COLORS.dark.persistence },
13410
- "orb-pattern": { color: ORB_COLORS.dark.pattern },
13411
- "orb-behavior": { color: ORB_COLORS.dark.behavior },
13412
- "orb-unknown-op": { color: ORB_COLORS.dark.error, textDecoration: "wavy underline" },
13413
- "orb-op-arithmetic": { color: ORB_COLORS.dark.arithmetic, fontWeight: "bold" },
13414
- "orb-op-comparison": { color: ORB_COLORS.dark.comparison },
13415
- "orb-op-logic": { color: ORB_COLORS.dark.logic },
13416
- "orb-op-string": { color: ORB_COLORS.dark.string },
13417
- "orb-op-collection": { color: ORB_COLORS.dark.collection },
13418
- "orb-op-time": { color: ORB_COLORS.dark.time },
13419
- "orb-op-control": { color: ORB_COLORS.dark.control },
13420
- "orb-op-async": { color: ORB_COLORS.dark.async }
13421
- };
13422
- var orbStyle = { ...dark, ...orbStyleOverrides };
13423
- var loloStyleOverrides = {
13424
- "lolo-binding": { color: ORB_COLORS.dark.binding, fontWeight: "bold" },
13425
- "lolo-event": { color: ORB_COLORS.dark.event },
13426
- "lolo-effect": { color: ORB_COLORS.dark.effect, fontWeight: "bold" },
13427
- "keyword": { color: ORB_COLORS.dark.loloKeyword },
13428
- "lolo-constructor": { color: ORB_COLORS.dark.loloConstructor },
13429
- "lolo-arrow": { color: ORB_COLORS.dark.loloArrow },
13430
- "lolo-reference": { color: ORB_COLORS.dark.loloReference },
13431
- "lolo-type": { color: ORB_COLORS.dark.fieldType },
13432
- "lolo-persistence": { color: ORB_COLORS.dark.persistence },
13433
- "lolo-unknown-op": { color: ORB_COLORS.dark.error },
13434
- "lolo-op-arithmetic": { color: ORB_COLORS.dark.arithmetic, fontWeight: "bold" },
13435
- "lolo-op-comparison": { color: ORB_COLORS.dark.comparison },
13436
- "lolo-op-logic": { color: ORB_COLORS.dark.logic },
13437
- "lolo-op-string": { color: ORB_COLORS.dark.string },
13438
- "lolo-op-collection": { color: ORB_COLORS.dark.collection },
13439
- "lolo-op-time": { color: ORB_COLORS.dark.time },
13440
- "lolo-op-control": { color: ORB_COLORS.dark.control },
13441
- "lolo-op-async": { color: ORB_COLORS.dark.async }
13442
- };
13443
- var loloStyle = { ...dark, ...loloStyleOverrides };
13461
+ var orbStyleOverrides = (c) => ({
13462
+ "orb-binding": { color: c.binding, fontWeight: "bold" },
13463
+ "orb-effect": { color: c.effect, fontWeight: "bold" },
13464
+ "orb-event": { color: c.event },
13465
+ "orb-slot": { color: c.uiSlot },
13466
+ "orb-structural": { color: c.structural },
13467
+ "orb-field-type": { color: c.fieldType },
13468
+ "orb-persistence": { color: c.persistence },
13469
+ "orb-pattern": { color: c.pattern },
13470
+ "orb-behavior": { color: c.behavior },
13471
+ "orb-unknown-op": { color: c.error, textDecoration: "wavy underline" },
13472
+ "orb-op-arithmetic": { color: c.arithmetic, fontWeight: "bold" },
13473
+ "orb-op-comparison": { color: c.comparison },
13474
+ "orb-op-logic": { color: c.logic },
13475
+ "orb-op-string": { color: c.string },
13476
+ "orb-op-collection": { color: c.collection },
13477
+ "orb-op-time": { color: c.time },
13478
+ "orb-op-control": { color: c.control },
13479
+ "orb-op-async": { color: c.async }
13480
+ });
13481
+ var loloStyleOverrides = (c) => ({
13482
+ "lolo-binding": { color: c.binding, fontWeight: "bold" },
13483
+ "lolo-event": { color: c.event },
13484
+ "lolo-effect": { color: c.effect, fontWeight: "bold" },
13485
+ "keyword": { color: c.loloKeyword },
13486
+ "lolo-constructor": { color: c.loloConstructor },
13487
+ "lolo-arrow": { color: c.loloArrow },
13488
+ "lolo-reference": { color: c.loloReference },
13489
+ "lolo-type": { color: c.fieldType },
13490
+ "lolo-persistence": { color: c.persistence },
13491
+ "lolo-unknown-op": { color: c.error },
13492
+ "lolo-op-arithmetic": { color: c.arithmetic, fontWeight: "bold" },
13493
+ "lolo-op-comparison": { color: c.comparison },
13494
+ "lolo-op-logic": { color: c.logic },
13495
+ "lolo-op-string": { color: c.string },
13496
+ "lolo-op-collection": { color: c.collection },
13497
+ "lolo-op-time": { color: c.time },
13498
+ "lolo-op-control": { color: c.control },
13499
+ "lolo-op-async": { color: c.async }
13500
+ });
13501
+ var SCHEME_BASE = { dark, light };
13502
+ var HIGHLIGHT_STYLES = {
13503
+ dark: {
13504
+ orb: { ...dark, ...orbStyleOverrides(ORB_COLORS.dark) },
13505
+ lolo: { ...dark, ...loloStyleOverrides(ORB_COLORS.dark) }
13506
+ },
13507
+ light: {
13508
+ orb: { ...light, ...orbStyleOverrides(ORB_COLORS.light) },
13509
+ lolo: { ...light, ...loloStyleOverrides(ORB_COLORS.light) }
13510
+ }
13511
+ };
13444
13512
  function computeFoldRegions(code) {
13445
13513
  const lines = code.split("\n");
13446
13514
  const regions = [];
@@ -13491,6 +13559,38 @@ function withTokenTypes(node) {
13491
13559
  function renderWithTokenTypes({ rows: rows2, stylesheet, useInlineStyles }) {
13492
13560
  return rows2.map((node, i) => createHighlightElement({ node: withTokenTypes(node), stylesheet, useInlineStyles, key: `code-segment-${i}` }));
13493
13561
  }
13562
+ var LTR_WORD = /[A-Za-z0-9_$@?][A-Za-z0-9_$@?.!-]*/g;
13563
+ var LTR_ISLAND_STYLE = { unicodeBidi: "isolate", direction: "ltr" };
13564
+ var STRING_ISLAND_STYLE = { unicodeBidi: "plaintext" };
13565
+ function island(value, style) {
13566
+ return { type: "element", tagName: "span", properties: { className: [], "data-bidi-island": "", style }, children: [{ type: "text", value }] };
13567
+ }
13568
+ function splitLtrWords(value) {
13569
+ const out = [];
13570
+ let last = 0;
13571
+ for (const match of value.matchAll(LTR_WORD)) {
13572
+ const start = match.index ?? 0;
13573
+ if (start > last) out.push({ type: "text", value: value.slice(last, start) });
13574
+ out.push(island(match[0], LTR_ISLAND_STYLE));
13575
+ last = start + match[0].length;
13576
+ }
13577
+ if (last < value.length) out.push({ type: "text", value: value.slice(last) });
13578
+ return out;
13579
+ }
13580
+ function withBidiIslands(node) {
13581
+ if (node.type === "text") return splitLtrWords(String(node.value ?? ""));
13582
+ if (node.type !== "element") return [node];
13583
+ const classes = node.properties?.className;
13584
+ if (Array.isArray(classes) && classes.includes("string")) {
13585
+ return [{ ...node, properties: { ...node.properties, className: classes, "data-bidi-island": "", style: STRING_ISLAND_STYLE } }];
13586
+ }
13587
+ return [{ ...node, ...node.children ? { children: node.children.flatMap(withBidiIslands) } : {} }];
13588
+ }
13589
+ function renderRtlCode({ rows: rows2, stylesheet, useInlineStyles }) {
13590
+ return rows2.map(
13591
+ (node, i) => withBidiIslands(node).map((n, j) => createHighlightElement({ node: n, stylesheet, useInlineStyles, key: `code-rtl-${i}-${j}` }))
13592
+ );
13593
+ }
13494
13594
  function tokenClassAt(layer, offset) {
13495
13595
  const walker = document.createTreeWalker(layer, NodeFilter.SHOW_TEXT);
13496
13596
  let pos = 0;
@@ -13646,11 +13746,10 @@ function useLanguageReady(language) {
13646
13746
  }, [language]);
13647
13747
  return ready;
13648
13748
  }
13649
- var MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace';
13650
- function resolveHighlightStyle(lang) {
13651
- if (lang === "orb") return orbStyle;
13652
- if (lang === "lolo") return loloStyle;
13653
- return dark;
13749
+ var MONO_FONT_FAMILY = 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", "IBM Plex Sans Arabic", "Noto Sans Arabic", monospace';
13750
+ function resolveHighlightStyle(lang, scheme) {
13751
+ if (lang === "orb" || lang === "lolo") return HIGHLIGHT_STYLES[scheme][lang];
13752
+ return SCHEME_BASE[scheme];
13654
13753
  }
13655
13754
  function plainCodeColorOf(style) {
13656
13755
  return style['code[class*="language-"]']?.color ?? "#d4d4d4";
@@ -13684,6 +13783,15 @@ var VIEWER_LINE_NUMBER_STYLE = {
13684
13783
  opacity: 0.5,
13685
13784
  fontVariantNumeric: "tabular-nums"
13686
13785
  };
13786
+ var VIEWER_LINE_NUMBER_STYLE_RTL = {
13787
+ minWidth: "2.5em",
13788
+ paddingRight: 0,
13789
+ paddingLeft: "1rem",
13790
+ textAlign: "left",
13791
+ userSelect: "none",
13792
+ opacity: 0.5,
13793
+ fontVariantNumeric: "tabular-nums"
13794
+ };
13687
13795
  function translateProgram(source, language, lang) {
13688
13796
  if (lang === "en") return source;
13689
13797
  if (language === "lolo") return translateLolo(source, lang);
@@ -13772,8 +13880,12 @@ var CodeBlock = React86__default.memo(
13772
13880
  }) => {
13773
13881
  const englishCode = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
13774
13882
  const naturalTabs = !editable && naturalLanguages && naturalLanguages.length > 1 ? naturalLanguages : void 0;
13775
- const [naturalLanguage, setNaturalLanguage] = useState(() => naturalTabs?.[0] ?? "en");
13883
+ const { locale: pageLocale } = useTranslate();
13884
+ const [naturalLanguage, setNaturalLanguage] = useState(
13885
+ () => naturalTabs?.find((lang) => lang === pageLocale) ?? naturalTabs?.[0] ?? "en"
13886
+ );
13776
13887
  const activeNaturalLanguage = naturalTabs?.includes(naturalLanguage) === true ? naturalLanguage : naturalTabs?.[0] ?? "en";
13888
+ const codeDir = naturalTabs && coreTables[activeNaturalLanguage].meta.rtl ? "rtl" : "ltr";
13777
13889
  const translationCache = useMemo(() => /* @__PURE__ */ new Map(), [englishCode, files]);
13778
13890
  const translateFor = useCallback(
13779
13891
  (source, sourceLanguage, cacheKey) => {
@@ -13812,11 +13924,12 @@ var CodeBlock = React86__default.memo(
13812
13924
  )
13813
13925
  }
13814
13926
  ) : null;
13815
- const activeStyle = resolveHighlightStyle(language);
13927
+ const activeStyle = resolveHighlightStyle(language, "dark");
13816
13928
  const overCapacity = code.length > HIGHLIGHT_CAPACITY_BYTES;
13817
13929
  const plainCodeColor = plainCodeColorOf(activeStyle);
13818
13930
  const eventBus = useEventBus();
13819
13931
  const { t } = useTranslate();
13932
+ const { resolvedMode } = useTheme();
13820
13933
  const scrollRef = useRef(null);
13821
13934
  const codeRef = useRef(null);
13822
13935
  const savedScrollLeftRef = useRef(0);
@@ -13827,7 +13940,7 @@ var CodeBlock = React86__default.memo(
13827
13940
  const activeLanguage = activeFile?.language ?? language;
13828
13941
  const activeCode = activeFile ? translateFor(activeFile.code, activeLanguage, `file-${activeFileIndex}`) : code;
13829
13942
  const languageReady = useLanguageReady(activeLanguage);
13830
- const viewerStyle = resolveHighlightStyle(activeLanguage);
13943
+ const viewerStyle = resolveHighlightStyle(activeLanguage, resolvedMode);
13831
13944
  const viewerPlainCodeColor = plainCodeColorOf(viewerStyle);
13832
13945
  const diffLines = useMemo(() => {
13833
13946
  if (propDiff && propDiff.length > 0) return propDiff;
@@ -14165,8 +14278,9 @@ var CodeBlock = React86__default.memo(
14165
14278
  wrapLines: true,
14166
14279
  wrapLongLines: wrap,
14167
14280
  showLineNumbers,
14168
- lineNumberStyle: VIEWER_LINE_NUMBER_STYLE,
14281
+ lineNumberStyle: codeDir === "rtl" ? VIEWER_LINE_NUMBER_STYLE_RTL : VIEWER_LINE_NUMBER_STYLE,
14169
14282
  lineProps: viewerLineProps,
14283
+ renderer: codeDir === "rtl" ? renderRtlCode : void 0,
14170
14284
  customStyle: {
14171
14285
  backgroundColor: "transparent",
14172
14286
  borderRadius: 0,
@@ -14176,13 +14290,15 @@ var CodeBlock = React86__default.memo(
14176
14290
  wordBreak: wrap ? "break-all" : "normal",
14177
14291
  fontFamily: MONO_FONT_FAMILY,
14178
14292
  fontSize: "12px",
14179
- lineHeight: "1.6"
14293
+ lineHeight: "1.6",
14294
+ direction: codeDir,
14295
+ textAlign: "start"
14180
14296
  },
14181
- codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6" } },
14297
+ codeTagProps: { style: { fontFamily: MONO_FONT_FAMILY, fontSize: "12px", lineHeight: "1.6", direction: codeDir, textAlign: "start" } },
14182
14298
  children: activeCode
14183
14299
  }
14184
14300
  ),
14185
- [activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady]
14301
+ [activeCode, viewerOverCapacity, viewerPlainCodeColor, activeLanguage, viewerStyle, wrap, showLineNumbers, viewerLineProps, languageReady, codeDir]
14186
14302
  );
14187
14303
  const diffOverCapacity = useMemo(
14188
14304
  () => !!diffLines && diffLines.reduce((n, l) => n + l.content.length + 1, 0) > HIGHLIGHT_CAPACITY_BYTES,
@@ -14452,33 +14568,35 @@ var CodeBlock = React86__default.memo(
14452
14568
  ]
14453
14569
  }
14454
14570
  ),
14455
- /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, dir: "ltr", children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
14571
+ /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight }, dir: codeDir, children: diffLines ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column" }, className: "font-mono text-xs", children: diffRowElements }) : /* @__PURE__ */ jsx("div", { className: "font-mono text-xs", children: viewerHighlightedElement }) })
14456
14572
  ] }) });
14457
14573
  }
14458
- const hasHeader = showLanguageBadge || effectiveCopy;
14574
+ const hasHeader = showLanguageBadge;
14575
+ const copyButton = effectiveCopy ? /* @__PURE__ */ jsx(
14576
+ Button,
14577
+ {
14578
+ variant: "ghost",
14579
+ size: "sm",
14580
+ onClick: handleCopy,
14581
+ className: `opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity text-muted-foreground hover:text-foreground${hasHeader ? "" : " absolute top-2 end-2 z-10"}`,
14582
+ "aria-label": t("common.copy"),
14583
+ children: copied ? /* @__PURE__ */ jsx(Icon, { name: "check", className: "w-4 h-4 text-success" }) : /* @__PURE__ */ jsx(Icon, { name: "copy", className: "w-4 h-4" })
14584
+ }
14585
+ ) : null;
14459
14586
  return /* @__PURE__ */ jsxs(Box, { ...domPassthrough(a11yRest), className: `relative group not-prose ${className || ""}`, style: { display: "flex", flexDirection: "column", height: "100%" }, children: [
14460
- hasHeader && /* @__PURE__ */ jsxs(
14587
+ hasHeader ? /* @__PURE__ */ jsxs(
14461
14588
  HStack,
14462
14589
  {
14463
14590
  justify: "between",
14464
14591
  align: "center",
14465
14592
  className: "px-3 py-2 bg-[var(--color-card)] rounded-t-container border-b border-border",
14593
+ "data-testid": "code-block-header",
14466
14594
  children: [
14467
- showLanguageBadge && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: language }),
14468
- effectiveCopy && /* @__PURE__ */ jsx(
14469
- Button,
14470
- {
14471
- variant: "ghost",
14472
- size: "sm",
14473
- onClick: handleCopy,
14474
- className: "opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity text-muted-foreground hover:text-foreground",
14475
- "aria-label": t("common.copy"),
14476
- children: copied ? /* @__PURE__ */ jsx(Icon, { name: "check", className: "w-4 h-4 text-success" }) : /* @__PURE__ */ jsx(Icon, { name: "copy", className: "w-4 h-4" })
14477
- }
14478
- )
14595
+ /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: language }),
14596
+ copyButton
14479
14597
  ]
14480
14598
  }
14481
- ),
14599
+ ) : copyButton,
14482
14600
  naturalTabStrip,
14483
14601
  editable ? (
14484
14602
  /* GAP-77 / GAP-82 / GAP-83: editable mode = transparent textarea on
@@ -24324,7 +24442,7 @@ function DataList({
24324
24442
  return f3.variant === "badge" ? (
24325
24443
  // `format` applies here too — a boolean field badged
24326
24444
  // without it renders the raw "false" instead of "No".
24327
- /* @__PURE__ */ jsx(Badge, { variant: badgeVariantFor(String(v), f3.colorMap), children: formatValue2(v, f3.format, fmt, relationsData?.[f3.name]) }, f3.name)
24445
+ /* @__PURE__ */ jsx(Badge, { variant: badgeVariantFor(String(v), f3.colorMap), children: valueLabelFor(formatValue2(v, f3.format, fmt, relationsData?.[f3.name]), f3.labels) }, f3.name)
24328
24446
  ) : /* @__PURE__ */ jsx(
24329
24447
  Typography,
24330
24448
  {
@@ -24487,7 +24605,7 @@ function DataList({
24487
24605
  if (val === void 0 || val === null || val === "") return null;
24488
24606
  return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
24489
24607
  field.icon && renderIconInput2(field.icon, { size: "xs" }),
24490
- /* @__PURE__ */ jsx(Badge, { variant: badgeVariantFor(String(val), field.colorMap), children: formatValue2(val, field.format, fmt, relationsData?.[field.name]) })
24608
+ /* @__PURE__ */ jsx(Badge, { variant: badgeVariantFor(String(val), field.colorMap), children: valueLabelFor(formatValue2(val, field.format, fmt, relationsData?.[field.name]), field.labels) })
24491
24609
  ] }, field.name);
24492
24610
  })
24493
24611
  ] }),
@@ -24935,8 +25053,8 @@ var MapViewImpl = lazy(async () => {
24935
25053
  shadowSize: [41, 41]
24936
25054
  });
24937
25055
  L.Marker.prototype.options.icon = defaultIcon;
24938
- const { useEffect: useEffect64, useRef: useRef65, useCallback: useCallback78, useState: useState94 } = React86__default;
24939
- const { Typography: Typography2 } = await import('./Typography-JGSDH4JP.js');
25056
+ const { useEffect: useEffect64, useRef: useRef65, useCallback: useCallback79, useState: useState94 } = React86__default;
25057
+ const { Typography: Typography2 } = await import('./Typography-CFI7JUVE.js');
24940
25058
  const { useEventBus: useEventBus2 } = await import('./useEventBus-JUAH3EFW.js');
24941
25059
  function MapUpdater({ centerLat, centerLng, zoom }) {
24942
25060
  const map = useMap();
@@ -24984,7 +25102,7 @@ var MapViewImpl = lazy(async () => {
24984
25102
  const contentSurface = useContentSurface(surface);
24985
25103
  const eventBus = useEventBus2();
24986
25104
  const [clickedPosition, setClickedPosition] = useState94(null);
24987
- const handleMapClick = useCallback78((lat, lng) => {
25105
+ const handleMapClick = useCallback79((lat, lng) => {
24988
25106
  if (showClickedPin) {
24989
25107
  setClickedPosition({ lat, lng });
24990
25108
  }
@@ -24993,7 +25111,7 @@ var MapViewImpl = lazy(async () => {
24993
25111
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
24994
25112
  }
24995
25113
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
24996
- const handleMarkerClick = useCallback78((marker) => {
25114
+ const handleMarkerClick = useCallback79((marker) => {
24997
25115
  onMarkerClick?.(marker);
24998
25116
  if (markerClickEvent) {
24999
25117
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -27402,7 +27520,7 @@ var DocSidebarCategory = ({ item, depth }) => {
27402
27520
  className: cn(
27403
27521
  "h-auto w-full justify-start rounded-interactive px-3 py-1.5 text-sm font-normal",
27404
27522
  depth > 0 && "ml-2",
27405
- item.active ? "bg-primary/8 text-foreground font-semibold" : "text-muted-foreground"
27523
+ item.active ? "bg-primary/[0.08] text-foreground font-semibold" : "text-muted-foreground"
27406
27524
  ),
27407
27525
  children: label
27408
27526
  }
@@ -34296,11 +34414,23 @@ var Header = ({
34296
34414
  variant = "mobile",
34297
34415
  look = "compact-bar",
34298
34416
  onLogoClick,
34417
+ brandHref,
34299
34418
  className,
34300
34419
  ...rest
34301
34420
  }) => {
34302
34421
  const { t } = useTranslate();
34303
34422
  const resolvedSearchPlaceholder = searchPlaceholder ?? t("common.search");
34423
+ const brandContent = /* @__PURE__ */ jsxs(Fragment, { children: [
34424
+ logo ? typeof logo === "string" ? /* @__PURE__ */ jsx(Avatar, { src: logo, alt: brandName, size: "sm" }) : logo : logoSrc ? /* @__PURE__ */ jsx(Avatar, { src: logoSrc, alt: brandName, size: "sm" }) : null,
34425
+ brandName && /* @__PURE__ */ jsx(
34426
+ Typography,
34427
+ {
34428
+ variant: "h5",
34429
+ className: "text-lg text-foreground",
34430
+ children: brandName
34431
+ }
34432
+ )
34433
+ ] });
34304
34434
  const userInitials = userAvatar?.initials || userName?.[0]?.toUpperCase() || "U";
34305
34435
  return /* @__PURE__ */ jsxs(
34306
34436
  Box,
@@ -34327,7 +34457,16 @@ var Header = ({
34327
34457
  children: isMenuOpen ? /* @__PURE__ */ jsx(X, { size: 24 }) : /* @__PURE__ */ jsx(Menu$1, { size: 24 })
34328
34458
  }
34329
34459
  ),
34330
- /* @__PURE__ */ jsxs(
34460
+ brandHref ? /* @__PURE__ */ jsx(
34461
+ Button,
34462
+ {
34463
+ variant: "ghost",
34464
+ href: brandHref,
34465
+ "aria-label": brandName,
34466
+ className: "gap-2 px-0 hover:bg-transparent",
34467
+ children: brandContent
34468
+ }
34469
+ ) : /* @__PURE__ */ jsx(
34331
34470
  HStack,
34332
34471
  {
34333
34472
  gap: "none",
@@ -34338,17 +34477,7 @@ var Header = ({
34338
34477
  ),
34339
34478
  ...pressableProps(onLogoClick),
34340
34479
  "aria-label": onLogoClick ? brandName : void 0,
34341
- children: [
34342
- logo ? typeof logo === "string" ? /* @__PURE__ */ jsx(Avatar, { src: logo, alt: brandName, size: "sm" }) : logo : logoSrc ? /* @__PURE__ */ jsx(Avatar, { src: logoSrc, alt: brandName, size: "sm" }) : null,
34343
- brandName && /* @__PURE__ */ jsx(
34344
- Typography,
34345
- {
34346
- variant: "h5",
34347
- className: "text-lg text-foreground",
34348
- children: brandName
34349
- }
34350
- )
34351
- ]
34480
+ children: brandContent
34352
34481
  }
34353
34482
  )
34354
34483
  ] }),
@@ -43293,8 +43422,8 @@ var VersionDiffInner = ({
43293
43422
  }
43294
43423
  ),
43295
43424
  /* @__PURE__ */ jsx(Box, { className: "overflow-auto bg-muted/20", style: { maxHeight: 600 }, children: isEmpty ? /* @__PURE__ */ jsx(Box, { className: "py-8", "data-testid": "version-diff-empty", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", align: "center", children: t("versionDiff.noChanges") }) }) : activeView === "side-by-side" ? /* @__PURE__ */ jsxs(Box, { className: "grid grid-cols-1 md:grid-cols-2", children: [
43296
- /* @__PURE__ */ jsx(Box, { className: "border-b md:border-b-0 md:border-r border-border", "data-testid": "version-diff-before", children: renderColumn("before") }),
43297
- /* @__PURE__ */ jsx(Box, { "data-testid": "version-diff-after", children: renderColumn("after") })
43425
+ /* @__PURE__ */ jsx(Box, { className: "min-w-0 overflow-x-auto border-b md:border-b-0 md:border-r border-border", "data-testid": "version-diff-before", children: renderColumn("before") }),
43426
+ /* @__PURE__ */ jsx(Box, { className: "min-w-0 overflow-x-auto", "data-testid": "version-diff-after", children: renderColumn("after") })
43298
43427
  ] }) : /* @__PURE__ */ jsx(VStack, { gap: "none", className: "font-mono text-xs", children: shown.map((row, idx) => {
43299
43428
  if (row.kind === "header") return renderHeader(row.header, `i-h-${idx}`);
43300
43429
  if (row.kind === "gap") return renderGap(row, `i-g-${row.id}`);
@@ -44201,6 +44330,7 @@ function UISlotComponentInner({
44201
44330
  const awaiting = isPortalSlot(slot) ? void 0 : awaitingSkeleton ?? runtimeAwaiting;
44202
44331
  const regionClassName = fallback !== void 0 ? cn("contents", className) : className;
44203
44332
  const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
44333
+ const i18n = useRenderI18n();
44204
44334
  const content = useMemo(() => {
44205
44335
  if (!rawContent) return rawContent;
44206
44336
  const resolvedProps = resolveRenderBindingMarkers(
@@ -44208,10 +44338,11 @@ function UISlotComponentInner({
44208
44338
  rawContent.sourceTrait,
44209
44339
  binding.entity,
44210
44340
  binding.config,
44211
- binding.state
44341
+ binding.state,
44342
+ i18n
44212
44343
  );
44213
44344
  return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
44214
- }, [rawContent, binding.entity, binding.config, binding.state]);
44345
+ }, [rawContent, binding.entity, binding.config, binding.state, i18n]);
44215
44346
  const animatedPortal = isAnimatedPortalSlot(slot);
44216
44347
  const holdForPending = useScopeHasPending(useContext(PendingScopeContext));
44217
44348
  const runtimePresence = useSlotPresence(portal && animatedPortal ? content ?? null : null, holdForPending);
@@ -44851,9 +44982,10 @@ function SlotContentRenderer({
44851
44982
  const ambientScope = useTraitScope();
44852
44983
  const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
44853
44984
  const binding = useEntityBindingSnapshot(bindingTrait);
44985
+ const i18n = useRenderI18n();
44854
44986
  const liveProps = useMemo(
44855
- () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
44856
- [content.props, bindingTrait, binding.entity, binding.config, binding.state]
44987
+ () => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state, i18n),
44988
+ [content.props, bindingTrait, binding.entity, binding.config, binding.state, i18n]
44857
44989
  );
44858
44990
  const propsObj = typeof liveProps === "string" ? {} : liveProps;
44859
44991
  const entityProp = propsObj.entity;