@almadar/ui 2.41.0 → 2.43.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.
@@ -293,7 +293,7 @@ var ThemeProvider = ({
293
293
  const newMode = resolvedMode === "dark" ? "light" : "dark";
294
294
  setMode(newMode);
295
295
  }, [resolvedMode, setMode]);
296
- const contextValue = React113.useMemo(
296
+ const contextValue2 = React113.useMemo(
297
297
  () => ({
298
298
  theme,
299
299
  mode,
@@ -315,30 +315,97 @@ var ThemeProvider = ({
315
315
  appliedTheme
316
316
  ]
317
317
  );
318
- return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: contextValue, children });
318
+ return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: contextValue2, children });
319
319
  };
320
320
  var store = /* @__PURE__ */ new Map();
321
321
  var storeListeners = /* @__PURE__ */ new Set();
322
322
  var watchCallbacks = /* @__PURE__ */ new Map();
323
- function advance(entityType, data) {
324
- const prev = store.get(entityType);
325
- const oldData = prev?.data ?? [];
326
- store.set(entityType, { data, version: (prev?.version ?? 0) + 1 });
323
+ function extractId(record) {
324
+ const r = record;
325
+ return String(r.id ?? r._id ?? r.key ?? "");
326
+ }
327
+ function materialize(snap) {
328
+ return snap.ids.map((id) => snap.entities.get(id));
329
+ }
330
+ function notifyListeners(entityType, prev) {
327
331
  for (const listener of storeListeners) {
328
332
  listener();
329
333
  }
330
334
  const cbs = watchCallbacks.get(entityType);
331
335
  if (cbs) {
336
+ const oldData = prev ? materialize(prev) : [];
337
+ const cur = store.get(entityType);
338
+ const newData = cur ? materialize(cur) : [];
332
339
  for (const cb of cbs) {
333
340
  try {
334
- cb(oldData, data);
341
+ cb(oldData, newData);
335
342
  } catch {
336
343
  }
337
344
  }
338
345
  }
339
346
  }
347
+ function setAll(entityType, records) {
348
+ const entities = /* @__PURE__ */ new Map();
349
+ const ids = [];
350
+ for (const r of records) {
351
+ const rec = r;
352
+ const id = extractId(rec);
353
+ if (id) {
354
+ entities.set(id, rec);
355
+ ids.push(id);
356
+ }
357
+ }
358
+ const prev = store.get(entityType);
359
+ store.set(entityType, { entities, ids, version: (prev?.version ?? 0) + 1 });
360
+ notifyListeners(entityType, prev);
361
+ }
362
+ function upsertOne(entityType, record) {
363
+ const id = extractId(record);
364
+ if (!id) return;
365
+ const prev = store.get(entityType);
366
+ const snapshot = prev ? { entities: new Map(prev.entities), ids: [...prev.ids], version: prev.version } : { entities: /* @__PURE__ */ new Map(), ids: [], version: 0 };
367
+ snapshot.entities.set(id, record);
368
+ if (!snapshot.ids.includes(id)) snapshot.ids.push(id);
369
+ snapshot.version++;
370
+ store.set(entityType, snapshot);
371
+ notifyListeners(entityType, prev);
372
+ }
373
+ function addOne(entityType, record) {
374
+ upsertOne(entityType, record);
375
+ }
376
+ function updateOne(entityType, id, changes) {
377
+ const prev = store.get(entityType);
378
+ if (!prev?.entities.has(id)) return;
379
+ const snapshot = {
380
+ entities: new Map(prev.entities),
381
+ ids: [...prev.ids],
382
+ version: prev.version
383
+ };
384
+ snapshot.entities.set(id, { ...snapshot.entities.get(id), ...changes });
385
+ snapshot.version++;
386
+ store.set(entityType, snapshot);
387
+ notifyListeners(entityType, prev);
388
+ }
389
+ function removeOne(entityType, id) {
390
+ const prev = store.get(entityType);
391
+ if (!prev) return;
392
+ const snapshot = {
393
+ entities: new Map(prev.entities),
394
+ ids: prev.ids.filter((i) => i !== id),
395
+ version: prev.version
396
+ };
397
+ snapshot.entities.delete(id);
398
+ snapshot.version++;
399
+ store.set(entityType, snapshot);
400
+ notifyListeners(entityType, prev);
401
+ }
340
402
  function getSnapshot(entityType) {
341
- return store.get(entityType)?.data ?? [];
403
+ const snap = store.get(entityType);
404
+ if (!snap) return [];
405
+ return materialize(snap);
406
+ }
407
+ function getById(entityType, id) {
408
+ return store.get(entityType)?.entities.get(id) ?? null;
342
409
  }
343
410
  function getVersion(entityType) {
344
411
  return store.get(entityType)?.version ?? 0;
@@ -373,6 +440,20 @@ function useEntityRef(entityType) {
373
440
  }, [entityType]);
374
441
  return React113.useSyncExternalStore(subscribeToStore, getSnapshotStable, () => []);
375
442
  }
443
+ function useEntityById(entityType, id) {
444
+ const versionRef = React113.useRef(0);
445
+ const dataRef = React113.useRef(null);
446
+ const getSnapshotStable = React113__namespace.default.useCallback(() => {
447
+ if (!id) return null;
448
+ const currentVersion = getVersion(entityType);
449
+ if (currentVersion !== versionRef.current) {
450
+ versionRef.current = currentVersion;
451
+ dataRef.current = getById(entityType, id);
452
+ }
453
+ return dataRef.current;
454
+ }, [entityType, id]);
455
+ return React113.useSyncExternalStore(subscribeToStore, getSnapshotStable, () => null);
456
+ }
376
457
  function useEntityWatch(entityType, callback) {
377
458
  const callbackRef = React113.useRef(callback);
378
459
  callbackRef.current = callback;
@@ -382,15 +463,21 @@ function useEntityWatch(entityType, callback) {
382
463
  });
383
464
  }, [entityType]);
384
465
  }
385
- var EntityStoreContext = React113.createContext({
386
- advance,
387
- getSnapshot
388
- });
466
+ var contextValue = {
467
+ setAll,
468
+ upsertOne,
469
+ addOne,
470
+ updateOne,
471
+ removeOne,
472
+ getSnapshot,
473
+ getById
474
+ };
475
+ var EntityStoreContext = React113.createContext(contextValue);
389
476
  function useEntityStore() {
390
477
  return React113.useContext(EntityStoreContext);
391
478
  }
392
479
  function EntityStoreProvider({ children }) {
393
- return /* @__PURE__ */ jsxRuntime.jsx(EntityStoreContext.Provider, { value: { advance, getSnapshot }, children });
480
+ return /* @__PURE__ */ jsxRuntime.jsx(EntityStoreContext.Provider, { value: contextValue, children });
394
481
  }
395
482
  function setGlobalEventBus(bus) {
396
483
  if (typeof window !== "undefined") {
@@ -565,7 +652,7 @@ function EventBusProvider({ children, debug: debug2 = false }) {
565
652
  }
566
653
  };
567
654
  }, [debug2]);
568
- const contextValue = React113.useMemo(
655
+ const contextValue2 = React113.useMemo(
569
656
  () => ({
570
657
  emit,
571
658
  on,
@@ -578,12 +665,12 @@ function EventBusProvider({ children, debug: debug2 = false }) {
578
665
  [emit, on, once, hasListeners, onAny, getSelectedEntity, clearSelectedEntity]
579
666
  );
580
667
  React113.useEffect(() => {
581
- setGlobalEventBus(contextValue);
668
+ setGlobalEventBus(contextValue2);
582
669
  return () => {
583
670
  setGlobalEventBus(null);
584
671
  };
585
- }, [contextValue]);
586
- return /* @__PURE__ */ jsxRuntime.jsx(EventBusContext2.Provider, { value: contextValue, children });
672
+ }, [contextValue2]);
673
+ return /* @__PURE__ */ jsxRuntime.jsx(EventBusContext2.Provider, { value: contextValue2, children });
587
674
  }
588
675
  var SelectionContext = React113.createContext(null);
589
676
  var defaultCompareEntities = (a, b) => {
@@ -653,13 +740,13 @@ function SelectionProvider({
653
740
  unsubCancel();
654
741
  };
655
742
  }, [eventBus, setSelected, clearSelection, debug2]);
656
- const contextValue = {
743
+ const contextValue2 = {
657
744
  selected,
658
745
  setSelected,
659
746
  clearSelection,
660
747
  isSelected
661
748
  };
662
- return /* @__PURE__ */ jsxRuntime.jsx(SelectionContext.Provider, { value: contextValue, children });
749
+ return /* @__PURE__ */ jsxRuntime.jsx(SelectionContext.Provider, { value: contextValue2, children });
663
750
  }
664
751
  function useSelection() {
665
752
  const context = React113.useContext(SelectionContext);
@@ -3052,13 +3139,13 @@ function getState() {
3052
3139
  }
3053
3140
  return { checks: /* @__PURE__ */ new Map(), transitions: [], bridgeHealth: null, listeners: /* @__PURE__ */ new Set() };
3054
3141
  }
3055
- function notifyListeners() {
3142
+ function notifyListeners2() {
3056
3143
  getState().listeners.forEach((l) => l());
3057
3144
  exposeOnWindow();
3058
3145
  }
3059
3146
  function registerCheck(id, label, status = "pending", details) {
3060
3147
  getState().checks.set(id, { id, label, status, details, updatedAt: Date.now() });
3061
- notifyListeners();
3148
+ notifyListeners2();
3062
3149
  }
3063
3150
  function getAllChecks() {
3064
3151
  return Array.from(getState().checks.values());
@@ -3102,7 +3189,7 @@ function recordTransition(trace) {
3102
3189
  failedEffects.map((e) => `${e.type}: ${e.error}`).join("; ")
3103
3190
  );
3104
3191
  }
3105
- notifyListeners();
3192
+ notifyListeners2();
3106
3193
  }
3107
3194
  function getTransitions() {
3108
3195
  return [...getState().transitions];
@@ -3348,6 +3435,42 @@ var orbStyleOverrides = {
3348
3435
  "orb-op-async": { color: syntax.ORB_COLORS.dark.async }
3349
3436
  };
3350
3437
  var orbStyle = { ...dark__default.default, ...orbStyleOverrides };
3438
+ function computeFoldRegions(code) {
3439
+ const lines = code.split("\n");
3440
+ const regions = [];
3441
+ const stack = [];
3442
+ for (let i = 0; i < lines.length; i++) {
3443
+ const line = lines[i];
3444
+ let inString = false;
3445
+ for (let j = 0; j < line.length; j++) {
3446
+ const ch = line[j];
3447
+ if (ch === "\\" && inString) {
3448
+ j++;
3449
+ continue;
3450
+ }
3451
+ if (ch === '"') {
3452
+ inString = !inString;
3453
+ continue;
3454
+ }
3455
+ if (inString) continue;
3456
+ if (ch === "{" || ch === "[") {
3457
+ stack.push({ line: i, bracket: ch });
3458
+ } else if (ch === "}" || ch === "]") {
3459
+ const open = stack.pop();
3460
+ if (open && open.line < i) {
3461
+ regions.push({
3462
+ start: open.line,
3463
+ end: i,
3464
+ closeBracket: ch
3465
+ });
3466
+ }
3467
+ }
3468
+ }
3469
+ }
3470
+ return regions.sort((a, b) => a.start - b.start);
3471
+ }
3472
+ var LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
3473
+ var HIDDEN_LINE_NUMBERS = { display: "none" };
3351
3474
  var CodeBlock = React113__namespace.default.memo(
3352
3475
  ({
3353
3476
  code: rawCode,
@@ -3355,6 +3478,7 @@ var CodeBlock = React113__namespace.default.memo(
3355
3478
  showCopyButton = true,
3356
3479
  showLanguageBadge = true,
3357
3480
  maxHeight = "60vh",
3481
+ foldable: foldableProp,
3358
3482
  className
3359
3483
  }) => {
3360
3484
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
@@ -3363,8 +3487,114 @@ var CodeBlock = React113__namespace.default.memo(
3363
3487
  const eventBus = useEventBus();
3364
3488
  const { t: _t } = useTranslate();
3365
3489
  const scrollRef = React113.useRef(null);
3490
+ const codeRef = React113.useRef(null);
3366
3491
  const savedScrollLeftRef = React113.useRef(0);
3367
3492
  const [copied, setCopied] = React113.useState(false);
3493
+ const isFoldable = foldableProp ?? (language === "orb" || language === "json");
3494
+ const [collapsed, setCollapsed] = React113.useState(() => /* @__PURE__ */ new Set());
3495
+ const foldRegions = React113.useMemo(
3496
+ () => isFoldable ? computeFoldRegions(code) : [],
3497
+ [code, isFoldable]
3498
+ );
3499
+ const foldStartMap = React113.useMemo(() => {
3500
+ const m = /* @__PURE__ */ new Map();
3501
+ for (const r of foldRegions) m.set(r.start, r);
3502
+ return m;
3503
+ }, [foldRegions]);
3504
+ const hiddenLines = React113.useMemo(() => {
3505
+ const h = /* @__PURE__ */ new Set();
3506
+ for (const r of foldRegions) {
3507
+ if (!collapsed.has(r.start)) continue;
3508
+ for (let i = r.start + 1; i <= r.end; i++) h.add(i);
3509
+ }
3510
+ return h;
3511
+ }, [foldRegions, collapsed]);
3512
+ const collapsedRef = React113.useRef(collapsed);
3513
+ collapsedRef.current = collapsed;
3514
+ const foldStartMapRef = React113.useRef(foldStartMap);
3515
+ foldStartMapRef.current = foldStartMap;
3516
+ const toggleFold = React113.useCallback((lineNum) => {
3517
+ setCollapsed((prev) => {
3518
+ const next = new Set(prev);
3519
+ if (next.has(lineNum)) next.delete(lineNum);
3520
+ else next.add(lineNum);
3521
+ return next;
3522
+ });
3523
+ }, []);
3524
+ const toggleFoldRef = React113.useRef(toggleFold);
3525
+ toggleFoldRef.current = toggleFold;
3526
+ React113.useEffect(() => {
3527
+ setCollapsed(/* @__PURE__ */ new Set());
3528
+ }, [code]);
3529
+ const highlightedElement = React113.useMemo(
3530
+ () => /* @__PURE__ */ jsxRuntime.jsx(
3531
+ SyntaxHighlighter__default.default,
3532
+ {
3533
+ PreTag: "div",
3534
+ language,
3535
+ style: activeStyle,
3536
+ wrapLines: true,
3537
+ showLineNumbers: true,
3538
+ showInlineLineNumbers: false,
3539
+ lineNumberContainerStyle: HIDDEN_LINE_NUMBERS,
3540
+ lineProps: LINE_PROPS_FN,
3541
+ customStyle: {
3542
+ backgroundColor: "transparent",
3543
+ borderRadius: 0,
3544
+ padding: 0,
3545
+ margin: 0,
3546
+ whiteSpace: "pre",
3547
+ minWidth: "100%"
3548
+ },
3549
+ children: code
3550
+ }
3551
+ ),
3552
+ [code, language, activeStyle]
3553
+ );
3554
+ React113.useLayoutEffect(() => {
3555
+ const container = codeRef.current;
3556
+ if (!container) return;
3557
+ container.querySelectorAll(".fold-toggle, .fold-summary").forEach((el) => el.remove());
3558
+ const lineEls = container.querySelectorAll("[data-line]");
3559
+ if (!isFoldable || foldRegions.length === 0) {
3560
+ lineEls.forEach((el) => {
3561
+ el.style.display = "";
3562
+ el.style.position = "";
3563
+ el.style.paddingLeft = "";
3564
+ });
3565
+ return;
3566
+ }
3567
+ lineEls.forEach((el) => {
3568
+ const num = parseInt(el.getAttribute("data-line") ?? "-1", 10);
3569
+ if (hiddenLines.has(num)) {
3570
+ el.style.display = "none";
3571
+ return;
3572
+ }
3573
+ el.style.display = "";
3574
+ el.style.position = "relative";
3575
+ el.style.paddingLeft = "1.2em";
3576
+ const region = foldStartMap.get(num);
3577
+ if (!region) return;
3578
+ const isCollapsed = collapsed.has(num);
3579
+ const toggle = document.createElement("span");
3580
+ toggle.className = "fold-toggle";
3581
+ toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
3582
+ toggle.style.cssText = "position:absolute;left:0;top:0;width:1.2em;text-align:center;cursor:pointer;color:#858585;font-size:10px;user-select:none;line-height:inherit;height:100%";
3583
+ toggle.addEventListener("click", (e) => {
3584
+ e.stopPropagation();
3585
+ toggleFoldRef.current(num);
3586
+ });
3587
+ el.insertBefore(toggle, el.firstChild);
3588
+ if (isCollapsed) {
3589
+ const summary = document.createElement("span");
3590
+ summary.className = "fold-summary";
3591
+ summary.style.cssText = "color:#858585;font-style:italic";
3592
+ const count = region.end - region.start - 1;
3593
+ summary.textContent = ` ... ${count} line${count !== 1 ? "s" : ""} ${region.closeBracket}`;
3594
+ el.appendChild(summary);
3595
+ }
3596
+ });
3597
+ }, [collapsed, hiddenLines, foldStartMap, foldRegions, isFoldable]);
3368
3598
  React113.useLayoutEffect(() => {
3369
3599
  const el = scrollRef.current;
3370
3600
  return () => {
@@ -3395,8 +3625,9 @@ var CodeBlock = React113__namespace.default.memo(
3395
3625
  eventBus.emit("UI:COPY_CODE", { language, success: false });
3396
3626
  }
3397
3627
  };
3628
+ const hasHeader = showLanguageBadge || showCopyButton;
3398
3629
  return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: `relative group ${className || ""}`, children: [
3399
- (showLanguageBadge || showCopyButton) && /* @__PURE__ */ jsxRuntime.jsxs(
3630
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs(
3400
3631
  HStack,
3401
3632
  {
3402
3633
  justify: "between",
@@ -3431,31 +3662,14 @@ var CodeBlock = React113__namespace.default.memo(
3431
3662
  touchAction: "pan-x pan-y",
3432
3663
  contain: "paint",
3433
3664
  backgroundColor: "#1e1e1e",
3434
- borderRadius: showLanguageBadge || showCopyButton ? "0 0 0.5rem 0.5rem" : "0.5rem",
3435
- padding: "1rem"
3665
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem"
3436
3666
  },
3437
- children: /* @__PURE__ */ jsxRuntime.jsx(
3438
- SyntaxHighlighter__default.default,
3439
- {
3440
- PreTag: "div",
3441
- language,
3442
- style: activeStyle,
3443
- customStyle: {
3444
- backgroundColor: "transparent",
3445
- borderRadius: 0,
3446
- padding: 0,
3447
- margin: 0,
3448
- whiteSpace: "pre",
3449
- minWidth: "100%"
3450
- },
3451
- children: code
3452
- }
3453
- )
3667
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: codeRef, style: { padding: "1rem" }, children: highlightedElement })
3454
3668
  }
3455
3669
  )
3456
3670
  ] });
3457
3671
  },
3458
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight
3672
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
3459
3673
  );
3460
3674
  CodeBlock.displayName = "CodeBlock";
3461
3675
 
@@ -3728,7 +3942,7 @@ function FetchedDataProvider({
3728
3942
  },
3729
3943
  [state.data]
3730
3944
  );
3731
- const getById = React113.useCallback(
3945
+ const getById2 = React113.useCallback(
3732
3946
  (entityName, id) => {
3733
3947
  const records = state.data[entityName];
3734
3948
  return records?.find((r) => r.id === id);
@@ -3792,10 +4006,10 @@ function FetchedDataProvider({
3792
4006
  const setError = React113.useCallback((error) => {
3793
4007
  setState((prev) => ({ ...prev, error, loading: false }));
3794
4008
  }, []);
3795
- const contextValue = React113.useMemo(
4009
+ const contextValue2 = React113.useMemo(
3796
4010
  () => ({
3797
4011
  getData,
3798
- getById,
4012
+ getById: getById2,
3799
4013
  hasData,
3800
4014
  getFetchedAt,
3801
4015
  setData,
@@ -3808,7 +4022,7 @@ function FetchedDataProvider({
3808
4022
  }),
3809
4023
  [
3810
4024
  getData,
3811
- getById,
4025
+ getById2,
3812
4026
  hasData,
3813
4027
  getFetchedAt,
3814
4028
  setData,
@@ -3820,7 +4034,7 @@ function FetchedDataProvider({
3820
4034
  setError
3821
4035
  ]
3822
4036
  );
3823
- return /* @__PURE__ */ jsxRuntime.jsx(FetchedDataContext.Provider, { value: contextValue, children });
4037
+ return /* @__PURE__ */ jsxRuntime.jsx(FetchedDataContext.Provider, { value: contextValue2, children });
3824
4038
  }
3825
4039
  function useFetchedDataContext() {
3826
4040
  return React113.useContext(FetchedDataContext);
@@ -3874,7 +4088,7 @@ function OfflineModeProvider({
3874
4088
  const [forceOffline, setForceOffline] = React113.useState(false);
3875
4089
  const executor = useOfflineExecutor(executorOptions);
3876
4090
  const effectivelyOffline = executor.isOffline || forceOffline;
3877
- const contextValue = React113.useMemo(
4091
+ const contextValue2 = React113.useMemo(
3878
4092
  () => ({
3879
4093
  ...executor,
3880
4094
  forceOffline,
@@ -3883,7 +4097,7 @@ function OfflineModeProvider({
3883
4097
  }),
3884
4098
  [executor, forceOffline, effectivelyOffline]
3885
4099
  );
3886
- return /* @__PURE__ */ jsxRuntime.jsx(OfflineModeContext.Provider, { value: contextValue, children });
4100
+ return /* @__PURE__ */ jsxRuntime.jsx(OfflineModeContext.Provider, { value: contextValue2, children });
3887
4101
  }
3888
4102
  function useOfflineMode() {
3889
4103
  const context = React113.useContext(OfflineModeContext);
@@ -3907,6 +4121,7 @@ exports.OrbitalProvider = OrbitalProvider;
3907
4121
  exports.SelectionContext = SelectionContext;
3908
4122
  exports.SelectionProvider = SelectionProvider;
3909
4123
  exports.VerificationProvider = VerificationProvider;
4124
+ exports.useEntityById = useEntityById;
3910
4125
  exports.useEntityRef = useEntityRef;
3911
4126
  exports.useEntityStore = useEntityStore;
3912
4127
  exports.useEntityWatch = useEntityWatch;
@@ -11,7 +11,7 @@ export { SelectionProvider, SelectionContext, useSelection, useSelectionOptional
11
11
  export type { SelectionContextType } from './SelectionProvider';
12
12
  export { FetchedDataProvider, FetchedDataContext, useFetchedDataContext, useFetchedData, useFetchedEntity, } from './FetchedDataProvider';
13
13
  export type { FetchedDataProviderProps, FetchedDataContextValue, FetchedDataState, EntityRecord, } from './FetchedDataProvider';
14
- export { EntityStoreProvider, EntityStoreContext, useEntityRef, useEntityWatch, useEntityStore, } from './EntityStoreProvider';
14
+ export { EntityStoreProvider, EntityStoreContext, useEntityRef, useEntityById, useEntityWatch, useEntityStore, } from './EntityStoreProvider';
15
15
  export type { EntityStoreContextValue } from './EntityStoreProvider';
16
16
  export { VerificationProvider } from './VerificationProvider';
17
17
  export type { VerificationProviderProps } from './VerificationProvider';