@camstack/ui-library 1.2.378 → 1.2.379

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.379] - 2026-11-03
11
+
12
+ ### Changed
13
+
14
+ - LogStream can offer an Origin filter (all / viewer app)
15
+ - Select keeps its themed background and text colour whatever a caller passes, and native option lists follow the theme, so dropdown options are readable in dark mode
16
+
10
17
  ## [1.2.378] - 2026-11-03
11
18
 
12
19
  ### Changed
@@ -42,6 +42,12 @@ export interface LogStreamProps {
42
42
  * live socket / handshake lines streaming during the test.
43
43
  */
44
44
  readonly requestId?: string;
45
+ /**
46
+ * Offer an "Origin" filter in the filter bar: all lines, or only the lines
47
+ * the viewer app shipped (`tags.source = 'viewer'`, set by the hub's client
48
+ * log ingest). Off by default; the system Logs page turns it on.
49
+ */
50
+ readonly showOriginFilter?: boolean;
45
51
  /** Initial log level filter. */
46
52
  readonly level?: "debug" | "info" | "warn" | "error";
47
53
  /** Max height CSS class (default: 'max-h-96'). */
@@ -75,7 +81,7 @@ export interface LogStreamProps {
75
81
  readonly onClose?: () => void;
76
82
  readonly className?: string;
77
83
  }
78
- export declare function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, level: initialLevel, maxHeight, showScope, showDeviceChip, showFilters, showSourceSelect, limit, liveBuffer: externalBuffer, onClose, className }: LogStreamProps): JSX.Element;
84
+ export declare function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, showOriginFilter, level: initialLevel, maxHeight, showScope, showDeviceChip, showFilters, showSourceSelect, limit, liveBuffer: externalBuffer, onClose, className }: LogStreamProps): JSX.Element;
79
85
  export interface FloatingLogStreamProps extends LogStreamProps {
80
86
  /** Position: 'bottom' anchors to parent bottom, 'overlay' is absolute positioned. */
81
87
  readonly position?: "bottom" | "overlay";
package/dist/index.cjs CHANGED
@@ -10634,7 +10634,7 @@ var Select = (0, react$1.forwardRef)(({ className, options, wrapperClassName, di
10634
10634
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
10635
10635
  ref,
10636
10636
  disabled,
10637
- className: cn("h-7 w-full px-2.5 text-xs bg-surface border border-border rounded-md text-foreground appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary", "disabled:opacity-50 disabled:cursor-not-allowed", className),
10637
+ className: cn("h-7 w-full px-2.5 text-xs border border-border rounded-md appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary", "disabled:opacity-50 disabled:cursor-not-allowed", className, "bg-surface text-foreground"),
10638
10638
  ...props,
10639
10639
  children: [options?.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
10640
10640
  value: option.value,
@@ -45265,13 +45265,14 @@ var TEXT_DEBOUNCE_MS = 300;
45265
45265
  /** Distance from the top (px) that asks for the next older page. */
45266
45266
  var TOP_LOAD_THRESHOLD_PX = 24;
45267
45267
  var BYTES_PER_MB = 1024 * 1024;
45268
- function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, level: initialLevel, maxHeight = "max-h-96", showScope = false, showDeviceChip = false, showFilters = true, showSourceSelect, limit = 100, liveBuffer: externalBuffer, onClose, className }) {
45268
+ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, showOriginFilter = false, level: initialLevel, maxHeight = "max-h-96", showScope = false, showDeviceChip = false, showFilters = true, showSourceSelect, limit = 100, liveBuffer: externalBuffer, onClose, className }) {
45269
45269
  const searchFieldRef = (0, react$1.useRef)(null);
45270
45270
  useSearchFieldHotkey(searchFieldRef);
45271
45271
  const t = useUiText();
45272
45272
  const sourceSelectOn = showSourceSelect ?? showFilters;
45273
45273
  const [localAddonId, setLocalAddonId] = (0, react$1.useState)("");
45274
45274
  const [localDeviceId, setLocalDeviceId] = (0, react$1.useState)("");
45275
+ const [viewerOnly, setViewerOnly] = (0, react$1.useState)(false);
45275
45276
  const [levelFilter, setLevelFilter] = (0, react$1.useState)(initialLevel ?? "info");
45276
45277
  const [sourceChoice, setSourceChoice] = (0, react$1.useState)(void 0);
45277
45278
  const agentId = propsAgentId;
@@ -45287,6 +45288,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45287
45288
  else if (deviceId !== void 0 && Number.isFinite(deviceId)) tags.deviceId = deviceId;
45288
45289
  if (integrationId) tags.integrationId = integrationId;
45289
45290
  if (requestId) tags.requestId = requestId;
45291
+ if (showOriginFilter && viewerOnly) tags.source = "viewer";
45290
45292
  return Object.keys(tags).length > 0 ? tags : void 0;
45291
45293
  }, [
45292
45294
  agentId,
@@ -45294,7 +45296,9 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45294
45296
  deviceId,
45295
45297
  propsContainerDeviceId,
45296
45298
  integrationId,
45297
- requestId
45299
+ requestId,
45300
+ showOriginFilter,
45301
+ viewerOnly
45298
45302
  ]);
45299
45303
  const fallbackBuffer = useLiveBuffer(MAX_LIVE_ENTRIES$1);
45300
45304
  const buffer = externalBuffer ?? fallbackBuffer;
@@ -45574,32 +45578,51 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45574
45578
  }),
45575
45579
  showFilters && (!propsAddonId || !propsDeviceId) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
45576
45580
  className: "flex items-center gap-2 px-3 py-1 border-b border-border/50 bg-surface/50 text-[10px]",
45577
- children: [!propsAddonId && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
45578
- className: "flex items-center gap-1",
45579
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
45580
- className: "text-foreground-subtle",
45581
- children: t("uiLibrary.logStream.addon", "Addon:")
45582
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
45583
- type: "text",
45584
- value: localAddonId,
45585
- onChange: (e) => setLocalAddonId(e.target.value),
45586
- placeholder: t("uiLibrary.logStream.all", "all"),
45587
- className: "w-28 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45588
- })]
45589
- }), !propsDeviceId && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
45590
- className: "flex items-center gap-1",
45591
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
45592
- className: "text-foreground-subtle",
45593
- children: t("uiLibrary.logStream.device", "Device:")
45594
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
45595
- type: "text",
45596
- inputMode: "numeric",
45597
- value: localDeviceId,
45598
- onChange: (e) => setLocalDeviceId(e.target.value),
45599
- placeholder: t("uiLibrary.logStream.all", "all"),
45600
- className: "w-16 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45601
- })]
45602
- })]
45581
+ children: [
45582
+ !propsAddonId && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
45583
+ className: "flex items-center gap-1",
45584
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
45585
+ className: "text-foreground-subtle",
45586
+ children: t("uiLibrary.logStream.addon", "Addon:")
45587
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
45588
+ type: "text",
45589
+ value: localAddonId,
45590
+ onChange: (e) => setLocalAddonId(e.target.value),
45591
+ placeholder: t("uiLibrary.logStream.all", "all"),
45592
+ className: "w-28 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45593
+ })]
45594
+ }),
45595
+ showOriginFilter && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
45596
+ className: "w-32",
45597
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Select, {
45598
+ "aria-label": t("uiLibrary.logStream.origin", "Origin"),
45599
+ className: "h-5 text-[10px]",
45600
+ value: viewerOnly ? "viewer" : "all",
45601
+ onChange: (e) => setViewerOnly(e.target.value === "viewer"),
45602
+ options: [{
45603
+ value: "all",
45604
+ label: t("uiLibrary.logStream.originAll", "All origins")
45605
+ }, {
45606
+ value: "viewer",
45607
+ label: t("uiLibrary.logStream.originViewer", "Viewer app")
45608
+ }]
45609
+ })
45610
+ }),
45611
+ !propsDeviceId && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
45612
+ className: "flex items-center gap-1",
45613
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
45614
+ className: "text-foreground-subtle",
45615
+ children: t("uiLibrary.logStream.device", "Device:")
45616
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
45617
+ type: "text",
45618
+ inputMode: "numeric",
45619
+ value: localDeviceId,
45620
+ onChange: (e) => setLocalDeviceId(e.target.value),
45621
+ placeholder: t("uiLibrary.logStream.all", "all"),
45622
+ className: "w-16 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45623
+ })]
45624
+ })
45625
+ ]
45603
45626
  }),
45604
45627
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
45605
45628
  className: "relative flex-1 min-h-0 flex flex-col",
@@ -73675,7 +73698,7 @@ function TimelineSlider({ markers, bands = [], selectedId = null, step = 5, aria
73675
73698
  }
73676
73699
  //#endregion
73677
73700
  //#region src/ui-library-version.ts
73678
- var uiLibraryVersion = "1.2.378";
73701
+ var uiLibraryVersion = "1.2.379";
73679
73702
  //#endregion
73680
73703
  //#region src/hooks/use-account-unit-preferences.ts
73681
73704
  /**
package/dist/index.js CHANGED
@@ -10610,7 +10610,7 @@ var Select = forwardRef(({ className, options, wrapperClassName, disabled, child
10610
10610
  children: [/* @__PURE__ */ jsxs("select", {
10611
10611
  ref,
10612
10612
  disabled,
10613
- className: cn("h-7 w-full px-2.5 text-xs bg-surface border border-border rounded-md text-foreground appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary", "disabled:opacity-50 disabled:cursor-not-allowed", className),
10613
+ className: cn("h-7 w-full px-2.5 text-xs border border-border rounded-md appearance-none pr-7 focus:outline-none focus:ring-1 focus:ring-primary", "disabled:opacity-50 disabled:cursor-not-allowed", className, "bg-surface text-foreground"),
10614
10614
  ...props,
10615
10615
  children: [options?.map((option) => /* @__PURE__ */ jsx("option", {
10616
10616
  value: option.value,
@@ -45241,13 +45241,14 @@ var TEXT_DEBOUNCE_MS = 300;
45241
45241
  /** Distance from the top (px) that asks for the next older page. */
45242
45242
  var TOP_LOAD_THRESHOLD_PX = 24;
45243
45243
  var BYTES_PER_MB = 1024 * 1024;
45244
- function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, level: initialLevel, maxHeight = "max-h-96", showScope = false, showDeviceChip = false, showFilters = true, showSourceSelect, limit = 100, liveBuffer: externalBuffer, onClose, className }) {
45244
+ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: propsDeviceId, containerDeviceId: propsContainerDeviceId, integrationId: propsIntegrationId, requestId: propsRequestId, showOriginFilter = false, level: initialLevel, maxHeight = "max-h-96", showScope = false, showDeviceChip = false, showFilters = true, showSourceSelect, limit = 100, liveBuffer: externalBuffer, onClose, className }) {
45245
45245
  const searchFieldRef = useRef(null);
45246
45246
  useSearchFieldHotkey(searchFieldRef);
45247
45247
  const t = useUiText();
45248
45248
  const sourceSelectOn = showSourceSelect ?? showFilters;
45249
45249
  const [localAddonId, setLocalAddonId] = useState("");
45250
45250
  const [localDeviceId, setLocalDeviceId] = useState("");
45251
+ const [viewerOnly, setViewerOnly] = useState(false);
45251
45252
  const [levelFilter, setLevelFilter] = useState(initialLevel ?? "info");
45252
45253
  const [sourceChoice, setSourceChoice] = useState(void 0);
45253
45254
  const agentId = propsAgentId;
@@ -45263,6 +45264,7 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45263
45264
  else if (deviceId !== void 0 && Number.isFinite(deviceId)) tags.deviceId = deviceId;
45264
45265
  if (integrationId) tags.integrationId = integrationId;
45265
45266
  if (requestId) tags.requestId = requestId;
45267
+ if (showOriginFilter && viewerOnly) tags.source = "viewer";
45266
45268
  return Object.keys(tags).length > 0 ? tags : void 0;
45267
45269
  }, [
45268
45270
  agentId,
@@ -45270,7 +45272,9 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45270
45272
  deviceId,
45271
45273
  propsContainerDeviceId,
45272
45274
  integrationId,
45273
- requestId
45275
+ requestId,
45276
+ showOriginFilter,
45277
+ viewerOnly
45274
45278
  ]);
45275
45279
  const fallbackBuffer = useLiveBuffer(MAX_LIVE_ENTRIES$1);
45276
45280
  const buffer = externalBuffer ?? fallbackBuffer;
@@ -45550,32 +45554,51 @@ function LogStream({ agentId: propsAgentId, addonId: propsAddonId, deviceId: pro
45550
45554
  }),
45551
45555
  showFilters && (!propsAddonId || !propsDeviceId) && /* @__PURE__ */ jsxs("div", {
45552
45556
  className: "flex items-center gap-2 px-3 py-1 border-b border-border/50 bg-surface/50 text-[10px]",
45553
- children: [!propsAddonId && /* @__PURE__ */ jsxs("label", {
45554
- className: "flex items-center gap-1",
45555
- children: [/* @__PURE__ */ jsx("span", {
45556
- className: "text-foreground-subtle",
45557
- children: t("uiLibrary.logStream.addon", "Addon:")
45558
- }), /* @__PURE__ */ jsx("input", {
45559
- type: "text",
45560
- value: localAddonId,
45561
- onChange: (e) => setLocalAddonId(e.target.value),
45562
- placeholder: t("uiLibrary.logStream.all", "all"),
45563
- className: "w-28 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45564
- })]
45565
- }), !propsDeviceId && /* @__PURE__ */ jsxs("label", {
45566
- className: "flex items-center gap-1",
45567
- children: [/* @__PURE__ */ jsx("span", {
45568
- className: "text-foreground-subtle",
45569
- children: t("uiLibrary.logStream.device", "Device:")
45570
- }), /* @__PURE__ */ jsx("input", {
45571
- type: "text",
45572
- inputMode: "numeric",
45573
- value: localDeviceId,
45574
- onChange: (e) => setLocalDeviceId(e.target.value),
45575
- placeholder: t("uiLibrary.logStream.all", "all"),
45576
- className: "w-16 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45577
- })]
45578
- })]
45557
+ children: [
45558
+ !propsAddonId && /* @__PURE__ */ jsxs("label", {
45559
+ className: "flex items-center gap-1",
45560
+ children: [/* @__PURE__ */ jsx("span", {
45561
+ className: "text-foreground-subtle",
45562
+ children: t("uiLibrary.logStream.addon", "Addon:")
45563
+ }), /* @__PURE__ */ jsx("input", {
45564
+ type: "text",
45565
+ value: localAddonId,
45566
+ onChange: (e) => setLocalAddonId(e.target.value),
45567
+ placeholder: t("uiLibrary.logStream.all", "all"),
45568
+ className: "w-28 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45569
+ })]
45570
+ }),
45571
+ showOriginFilter && /* @__PURE__ */ jsx("div", {
45572
+ className: "w-32",
45573
+ children: /* @__PURE__ */ jsx(Select, {
45574
+ "aria-label": t("uiLibrary.logStream.origin", "Origin"),
45575
+ className: "h-5 text-[10px]",
45576
+ value: viewerOnly ? "viewer" : "all",
45577
+ onChange: (e) => setViewerOnly(e.target.value === "viewer"),
45578
+ options: [{
45579
+ value: "all",
45580
+ label: t("uiLibrary.logStream.originAll", "All origins")
45581
+ }, {
45582
+ value: "viewer",
45583
+ label: t("uiLibrary.logStream.originViewer", "Viewer app")
45584
+ }]
45585
+ })
45586
+ }),
45587
+ !propsDeviceId && /* @__PURE__ */ jsxs("label", {
45588
+ className: "flex items-center gap-1",
45589
+ children: [/* @__PURE__ */ jsx("span", {
45590
+ className: "text-foreground-subtle",
45591
+ children: t("uiLibrary.logStream.device", "Device:")
45592
+ }), /* @__PURE__ */ jsx("input", {
45593
+ type: "text",
45594
+ inputMode: "numeric",
45595
+ value: localDeviceId,
45596
+ onChange: (e) => setLocalDeviceId(e.target.value),
45597
+ placeholder: t("uiLibrary.logStream.all", "all"),
45598
+ className: "w-16 px-1.5 py-0.5 rounded border border-border bg-background text-foreground text-[10px] focus:outline-none focus:border-primary/50"
45599
+ })]
45600
+ })
45601
+ ]
45579
45602
  }),
45580
45603
  /* @__PURE__ */ jsxs("div", {
45581
45604
  className: "relative flex-1 min-h-0 flex flex-col",
@@ -73651,7 +73674,7 @@ function TimelineSlider({ markers, bands = [], selectedId = null, step = 5, aria
73651
73674
  }
73652
73675
  //#endregion
73653
73676
  //#region src/ui-library-version.ts
73654
- var uiLibraryVersion = "1.2.378";
73677
+ var uiLibraryVersion = "1.2.379";
73655
73678
  //#endregion
73656
73679
  //#region src/hooks/use-account-unit-preferences.ts
73657
73680
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.2.378",
3
+ "version": "1.2.379",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/camstack/server.git",
@@ -84,6 +84,20 @@
84
84
  color-scheme: dark;
85
85
  }
86
86
 
87
+ /* Native form popups (select, option, optgroup) are painted by the UA from the element's own
88
+ colours; without these a transparent select shows white options with near-white text. */
89
+ select,
90
+ option,
91
+ optgroup {
92
+ background-color: var(--color-surface);
93
+ color: var(--color-foreground);
94
+ }
95
+
96
+ option:checked {
97
+ background-color: var(--color-primary);
98
+ color: var(--color-primary-foreground);
99
+ }
100
+
87
101
  /* Dark theme (default) */
88
102
  .dark {
89
103
  color-scheme: dark;