@camstack/ui-library 1.2.62 → 1.2.64

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.
@@ -76,6 +76,17 @@ export type CellState = {
76
76
  * "→ label" badge on the cell.
77
77
  */
78
78
  readonly jumpTo?: string;
79
+ /**
80
+ * This model is a CLUSTER-wide choice, not a per-(node,device) one — the
81
+ * step writes into a shared vector index, where two encoders make
82
+ * similarity scores meaningless.
83
+ *
84
+ * The cell must SAY so. Rendering a cluster value in a per-node matrix
85
+ * with no marking invites the operator to change it expecting a per-node
86
+ * effect, and to read a neighbouring node's identical value as a
87
+ * coincidence rather than as the same single row.
88
+ */
89
+ readonly clusterWide?: boolean;
79
90
  } | {
80
91
  readonly kind: 'disabled';
81
92
  readonly overridden?: boolean;
package/dist/index.cjs CHANGED
@@ -7161,6 +7161,115 @@ function useCustomFieldRenderer(type) {
7161
7161
  return (0, react$1.useContext)(CustomFieldRenderersContext)[type] ?? null;
7162
7162
  }
7163
7163
  //#endregion
7164
+ //#region src/composites/event-kind-visuals.tsx
7165
+ /**
7166
+ * Event-kind VISUALS — the UI-side half of the unified taxonomy dictionary
7167
+ * (`@camstack/types` `EVENT_TAXONOMY` owns the serializable data:
7168
+ * color / iconId / labelKey; this owns `iconId → lucide component` and
7169
+ * `labelKey → t()`).
7170
+ *
7171
+ * Every UI that renders an event kind (timeline, events tree, chips,
7172
+ * detection canvas/tree) resolves its glyph + translated label here — no
7173
+ * per-component hardcoded icon or label.
7174
+ */
7175
+ /**
7176
+ * `iconId` → lucide component. Built ONLY from statically-imported icons
7177
+ * (bundle-safe). Unknown ids resolve to the neutral `Tag` fallback.
7178
+ */
7179
+ var EVENT_KIND_ICONS = {
7180
+ motion: Activity,
7181
+ audio: Volume2,
7182
+ person: User,
7183
+ vehicle: Car,
7184
+ animal: PawPrint,
7185
+ package: Package,
7186
+ sensor: Radio,
7187
+ control: SlidersHorizontal,
7188
+ car: Car,
7189
+ truck: Truck,
7190
+ bus: Bus,
7191
+ motorcycle: Bike,
7192
+ bicycle: Bike,
7193
+ airplane: Plane,
7194
+ boat: Sailboat,
7195
+ train: TrainFront,
7196
+ bird: Bird,
7197
+ cat: Cat,
7198
+ dog: Dog,
7199
+ horse: PawPrint,
7200
+ sheep: PawPrint,
7201
+ cow: PawPrint,
7202
+ elephant: PawPrint,
7203
+ bear: PawPrint,
7204
+ zebra: PawPrint,
7205
+ giraffe: PawPrint,
7206
+ door: DoorOpen,
7207
+ pir: Radar,
7208
+ smoke: Flame,
7209
+ water: Droplet,
7210
+ gas: Wind,
7211
+ vibration: Vibrate,
7212
+ tamper: ShieldAlert,
7213
+ presence: UserCheck,
7214
+ generic: Tag,
7215
+ lock: Lock,
7216
+ siren: Siren,
7217
+ switch: ToggleRight,
7218
+ doorbell: BellRing,
7219
+ button: CircleDot,
7220
+ "audio-speech": MessageSquare,
7221
+ "audio-scream": Megaphone,
7222
+ "audio-crying": Baby,
7223
+ "audio-laughter": Laugh,
7224
+ "audio-music": Music,
7225
+ "audio-dog": Dog,
7226
+ "audio-cat": Cat,
7227
+ "audio-bird": Bird,
7228
+ "audio-animal": PawPrint,
7229
+ "audio-alarm": BellRing,
7230
+ "audio-doorbell": BellRing,
7231
+ "audio-glass_breaking": TriangleAlert,
7232
+ "audio-gunshot": Crosshair,
7233
+ "audio-vehicle": Car,
7234
+ "audio-siren": Siren,
7235
+ "audio-fire": Flame,
7236
+ "audio-water": Droplets,
7237
+ "audio-wind": Wind,
7238
+ "audio-door": DoorOpen,
7239
+ "audio-footsteps": Footprints,
7240
+ "audio-crowd": Users,
7241
+ "audio-telephone": Phone,
7242
+ "audio-engine": Cog,
7243
+ "audio-tools": Hammer,
7244
+ "audio-silence": VolumeX
7245
+ };
7246
+ /** Resolve an `iconId` to a lucide component (falls back to `Tag`). */
7247
+ function resolveEventKindIcon(iconId) {
7248
+ if (Object.hasOwn(EVENT_KIND_ICONS, iconId)) return EVENT_KIND_ICONS[iconId];
7249
+ if (iconId.startsWith("audio-")) return Volume2;
7250
+ return Tag;
7251
+ }
7252
+ /**
7253
+ * Translated label for an event kind — `t(labelKey)` when a translation
7254
+ * exists, else the English `label` fallback. Robust to a missing key: an
7255
+ * i18n backend that echoes the key unchanged (react-i18next default) is
7256
+ * treated as "no translation" and the fallback label is returned, so the UI
7257
+ * never renders a raw `eventKind.*` key.
7258
+ */
7259
+ function eventKindLabel(descriptor, t) {
7260
+ if (t === void 0) return descriptor.label;
7261
+ const translated = t(descriptor.labelKey);
7262
+ return translated === descriptor.labelKey || translated.length === 0 ? descriptor.label : translated;
7263
+ }
7264
+ /** Small convenience component: renders the lucide glyph for an `iconId`. */
7265
+ function EventKindGlyph({ iconId, size = 16, color, className }) {
7266
+ return (0, react$1.createElement)(resolveEventKindIcon(iconId), {
7267
+ size,
7268
+ color,
7269
+ className
7270
+ });
7271
+ }
7272
+ //#endregion
7164
7273
  //#region src/composites/confirm-dialog.tsx
7165
7274
  var ConfirmContext = createSharedContext("camstack:confirm-dialog", null);
7166
7275
  function useConfirm() {
@@ -19727,13 +19836,20 @@ function MultiSelectField({ field, value, onChange, disabled, translationFn }) {
19727
19836
  checked ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground hover:bg-surface",
19728
19837
  disabled || field.disabled ? "opacity-50 cursor-not-allowed" : ""
19729
19838
  ].join(" "),
19730
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
19731
- type: "checkbox",
19732
- className: "sr-only",
19733
- checked,
19734
- disabled: disabled || field.disabled,
19735
- onChange: () => toggle(opt.value)
19736
- }), opt.label]
19839
+ children: [
19840
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
19841
+ type: "checkbox",
19842
+ className: "sr-only",
19843
+ checked,
19844
+ disabled: disabled || field.disabled,
19845
+ onChange: () => toggle(opt.value)
19846
+ }),
19847
+ opt.iconId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EventKindGlyph, {
19848
+ iconId: opt.iconId,
19849
+ size: 13
19850
+ }),
19851
+ opt.label
19852
+ ]
19737
19853
  }, opt.value);
19738
19854
  })
19739
19855
  })
@@ -21615,7 +21731,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21615
21731
  const resolutions = [...new Set(tier.options.map((o) => o.resolution))].sort((a, b) => (b ?? Infinity) - (a ?? Infinity));
21616
21732
  const selectedResolution = resolutions.includes(current?.resolution) ? current?.resolution : resolutions[0];
21617
21733
  const variantOptions = tier.options.filter((o) => o.resolution === selectedResolution);
21618
- const resLabel = (r) => r === void 0 ? "640 · native" : `${r}`;
21734
+ const resLabel = (r) => r === void 0 ? "native" : `${r}`;
21619
21735
  const selectTier = (tierId) => {
21620
21736
  const t = family.tiers.find((x) => x.tier === tierId);
21621
21737
  if (!t) return;
@@ -21659,7 +21775,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21659
21775
  className: "grid grid-cols-2 gap-1.5 sm:grid-cols-4",
21660
21776
  children: family.tiers.map((t) => {
21661
21777
  const active = t.tier === tier.tier;
21662
- const base = t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
21778
+ const quoted = t.options.find((o) => o.resolution === selectedResolution && o.precision === "fp32") ?? t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
21663
21779
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
21664
21780
  type: "button",
21665
21781
  disabled,
@@ -21675,7 +21791,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21675
21791
  className: "text-[10px] text-foreground-subtle",
21676
21792
  children: [
21677
21793
  "~",
21678
- base?.sizeMB ?? 0,
21794
+ quoted?.sizeMB ?? 0,
21679
21795
  " MB"
21680
21796
  ]
21681
21797
  })]
@@ -21975,12 +22091,15 @@ function ConfigMultiSelect({ label, description, value, options, disabled, onCha
21975
22091
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
21976
22092
  className: "flex flex-wrap gap-1.5",
21977
22093
  children: options.map((o) => {
21978
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
22094
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
21979
22095
  type: "button",
21980
22096
  disabled,
21981
22097
  onClick: () => toggle(o.value),
21982
- className: cn("text-[10px] font-medium px-2 py-1 rounded-md border transition-colors", value.includes(o.value) ? "bg-primary/20 text-primary border-primary/40" : "bg-surface text-foreground-subtle border-border hover:border-primary/30", disabled && "opacity-50 cursor-not-allowed"),
21983
- children: o.label
22098
+ className: cn("inline-flex items-center gap-1 text-[10px] font-medium px-2 py-1 rounded-md border transition-colors", value.includes(o.value) ? "bg-primary/20 text-primary border-primary/40" : "bg-surface text-foreground-subtle border-border hover:border-primary/30", disabled && "opacity-50 cursor-not-allowed"),
22099
+ children: [o.iconId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EventKindGlyph, {
22100
+ iconId: o.iconId,
22101
+ size: 12
22102
+ }), o.label]
21984
22103
  }, o.value);
21985
22104
  })
21986
22105
  })
@@ -44079,6 +44198,11 @@ function renderCellContent(state) {
44079
44198
  className: "font-mono text-foreground truncate",
44080
44199
  children: state.modelId
44081
44200
  }),
44201
+ state.clusterWide === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
44202
+ className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-primary",
44203
+ title: "One value for the whole cluster — this step writes into a shared vector index",
44204
+ children: "cluster"
44205
+ }),
44082
44206
  state.jumpTo !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
44083
44207
  className: "ml-auto shrink-0 text-[8px] font-semibold text-sky-500",
44084
44208
  title: `runs on ${state.jumpTo}`,
@@ -44672,115 +44796,6 @@ function DoorbellRecentPanel({ history, limit = 5, latestIsFresh, className }) {
44672
44796
  });
44673
44797
  }
44674
44798
  //#endregion
44675
- //#region src/composites/event-kind-visuals.tsx
44676
- /**
44677
- * Event-kind VISUALS — the UI-side half of the unified taxonomy dictionary
44678
- * (`@camstack/types` `EVENT_TAXONOMY` owns the serializable data:
44679
- * color / iconId / labelKey; this owns `iconId → lucide component` and
44680
- * `labelKey → t()`).
44681
- *
44682
- * Every UI that renders an event kind (timeline, events tree, chips,
44683
- * detection canvas/tree) resolves its glyph + translated label here — no
44684
- * per-component hardcoded icon or label.
44685
- */
44686
- /**
44687
- * `iconId` → lucide component. Built ONLY from statically-imported icons
44688
- * (bundle-safe). Unknown ids resolve to the neutral `Tag` fallback.
44689
- */
44690
- var EVENT_KIND_ICONS = {
44691
- motion: Activity,
44692
- audio: Volume2,
44693
- person: User,
44694
- vehicle: Car,
44695
- animal: PawPrint,
44696
- package: Package,
44697
- sensor: Radio,
44698
- control: SlidersHorizontal,
44699
- car: Car,
44700
- truck: Truck,
44701
- bus: Bus,
44702
- motorcycle: Bike,
44703
- bicycle: Bike,
44704
- airplane: Plane,
44705
- boat: Sailboat,
44706
- train: TrainFront,
44707
- bird: Bird,
44708
- cat: Cat,
44709
- dog: Dog,
44710
- horse: PawPrint,
44711
- sheep: PawPrint,
44712
- cow: PawPrint,
44713
- elephant: PawPrint,
44714
- bear: PawPrint,
44715
- zebra: PawPrint,
44716
- giraffe: PawPrint,
44717
- door: DoorOpen,
44718
- pir: Radar,
44719
- smoke: Flame,
44720
- water: Droplet,
44721
- gas: Wind,
44722
- vibration: Vibrate,
44723
- tamper: ShieldAlert,
44724
- presence: UserCheck,
44725
- generic: Tag,
44726
- lock: Lock,
44727
- siren: Siren,
44728
- switch: ToggleRight,
44729
- doorbell: BellRing,
44730
- button: CircleDot,
44731
- "audio-speech": MessageSquare,
44732
- "audio-scream": Megaphone,
44733
- "audio-crying": Baby,
44734
- "audio-laughter": Laugh,
44735
- "audio-music": Music,
44736
- "audio-dog": Dog,
44737
- "audio-cat": Cat,
44738
- "audio-bird": Bird,
44739
- "audio-animal": PawPrint,
44740
- "audio-alarm": BellRing,
44741
- "audio-doorbell": BellRing,
44742
- "audio-glass_breaking": TriangleAlert,
44743
- "audio-gunshot": Crosshair,
44744
- "audio-vehicle": Car,
44745
- "audio-siren": Siren,
44746
- "audio-fire": Flame,
44747
- "audio-water": Droplets,
44748
- "audio-wind": Wind,
44749
- "audio-door": DoorOpen,
44750
- "audio-footsteps": Footprints,
44751
- "audio-crowd": Users,
44752
- "audio-telephone": Phone,
44753
- "audio-engine": Cog,
44754
- "audio-tools": Hammer,
44755
- "audio-silence": VolumeX
44756
- };
44757
- /** Resolve an `iconId` to a lucide component (falls back to `Tag`). */
44758
- function resolveEventKindIcon(iconId) {
44759
- if (Object.hasOwn(EVENT_KIND_ICONS, iconId)) return EVENT_KIND_ICONS[iconId];
44760
- if (iconId.startsWith("audio-")) return Volume2;
44761
- return Tag;
44762
- }
44763
- /**
44764
- * Translated label for an event kind — `t(labelKey)` when a translation
44765
- * exists, else the English `label` fallback. Robust to a missing key: an
44766
- * i18n backend that echoes the key unchanged (react-i18next default) is
44767
- * treated as "no translation" and the fallback label is returned, so the UI
44768
- * never renders a raw `eventKind.*` key.
44769
- */
44770
- function eventKindLabel(descriptor, t) {
44771
- if (t === void 0) return descriptor.label;
44772
- const translated = t(descriptor.labelKey);
44773
- return translated === descriptor.labelKey || translated.length === 0 ? descriptor.label : translated;
44774
- }
44775
- /** Small convenience component: renders the lucide glyph for an `iconId`. */
44776
- function EventKindGlyph({ iconId, size = 16, color, className }) {
44777
- return (0, react$1.createElement)(resolveEventKindIcon(iconId), {
44778
- size,
44779
- color,
44780
- className
44781
- });
44782
- }
44783
- //#endregion
44784
44799
  //#region src/composites/filter-bar.tsx
44785
44800
  function FilterBar({ filters, values, onChange, className }) {
44786
44801
  const isMobile = useIsMobile();
package/dist/index.js CHANGED
@@ -7137,6 +7137,115 @@ function useCustomFieldRenderer(type) {
7137
7137
  return useContext(CustomFieldRenderersContext)[type] ?? null;
7138
7138
  }
7139
7139
  //#endregion
7140
+ //#region src/composites/event-kind-visuals.tsx
7141
+ /**
7142
+ * Event-kind VISUALS — the UI-side half of the unified taxonomy dictionary
7143
+ * (`@camstack/types` `EVENT_TAXONOMY` owns the serializable data:
7144
+ * color / iconId / labelKey; this owns `iconId → lucide component` and
7145
+ * `labelKey → t()`).
7146
+ *
7147
+ * Every UI that renders an event kind (timeline, events tree, chips,
7148
+ * detection canvas/tree) resolves its glyph + translated label here — no
7149
+ * per-component hardcoded icon or label.
7150
+ */
7151
+ /**
7152
+ * `iconId` → lucide component. Built ONLY from statically-imported icons
7153
+ * (bundle-safe). Unknown ids resolve to the neutral `Tag` fallback.
7154
+ */
7155
+ var EVENT_KIND_ICONS = {
7156
+ motion: Activity,
7157
+ audio: Volume2,
7158
+ person: User,
7159
+ vehicle: Car,
7160
+ animal: PawPrint,
7161
+ package: Package,
7162
+ sensor: Radio,
7163
+ control: SlidersHorizontal,
7164
+ car: Car,
7165
+ truck: Truck,
7166
+ bus: Bus,
7167
+ motorcycle: Bike,
7168
+ bicycle: Bike,
7169
+ airplane: Plane,
7170
+ boat: Sailboat,
7171
+ train: TrainFront,
7172
+ bird: Bird,
7173
+ cat: Cat,
7174
+ dog: Dog,
7175
+ horse: PawPrint,
7176
+ sheep: PawPrint,
7177
+ cow: PawPrint,
7178
+ elephant: PawPrint,
7179
+ bear: PawPrint,
7180
+ zebra: PawPrint,
7181
+ giraffe: PawPrint,
7182
+ door: DoorOpen,
7183
+ pir: Radar,
7184
+ smoke: Flame,
7185
+ water: Droplet,
7186
+ gas: Wind,
7187
+ vibration: Vibrate,
7188
+ tamper: ShieldAlert,
7189
+ presence: UserCheck,
7190
+ generic: Tag,
7191
+ lock: Lock,
7192
+ siren: Siren,
7193
+ switch: ToggleRight,
7194
+ doorbell: BellRing,
7195
+ button: CircleDot,
7196
+ "audio-speech": MessageSquare,
7197
+ "audio-scream": Megaphone,
7198
+ "audio-crying": Baby,
7199
+ "audio-laughter": Laugh,
7200
+ "audio-music": Music,
7201
+ "audio-dog": Dog,
7202
+ "audio-cat": Cat,
7203
+ "audio-bird": Bird,
7204
+ "audio-animal": PawPrint,
7205
+ "audio-alarm": BellRing,
7206
+ "audio-doorbell": BellRing,
7207
+ "audio-glass_breaking": TriangleAlert,
7208
+ "audio-gunshot": Crosshair,
7209
+ "audio-vehicle": Car,
7210
+ "audio-siren": Siren,
7211
+ "audio-fire": Flame,
7212
+ "audio-water": Droplets,
7213
+ "audio-wind": Wind,
7214
+ "audio-door": DoorOpen,
7215
+ "audio-footsteps": Footprints,
7216
+ "audio-crowd": Users,
7217
+ "audio-telephone": Phone,
7218
+ "audio-engine": Cog,
7219
+ "audio-tools": Hammer,
7220
+ "audio-silence": VolumeX
7221
+ };
7222
+ /** Resolve an `iconId` to a lucide component (falls back to `Tag`). */
7223
+ function resolveEventKindIcon(iconId) {
7224
+ if (Object.hasOwn(EVENT_KIND_ICONS, iconId)) return EVENT_KIND_ICONS[iconId];
7225
+ if (iconId.startsWith("audio-")) return Volume2;
7226
+ return Tag;
7227
+ }
7228
+ /**
7229
+ * Translated label for an event kind — `t(labelKey)` when a translation
7230
+ * exists, else the English `label` fallback. Robust to a missing key: an
7231
+ * i18n backend that echoes the key unchanged (react-i18next default) is
7232
+ * treated as "no translation" and the fallback label is returned, so the UI
7233
+ * never renders a raw `eventKind.*` key.
7234
+ */
7235
+ function eventKindLabel(descriptor, t) {
7236
+ if (t === void 0) return descriptor.label;
7237
+ const translated = t(descriptor.labelKey);
7238
+ return translated === descriptor.labelKey || translated.length === 0 ? descriptor.label : translated;
7239
+ }
7240
+ /** Small convenience component: renders the lucide glyph for an `iconId`. */
7241
+ function EventKindGlyph({ iconId, size = 16, color, className }) {
7242
+ return createElement(resolveEventKindIcon(iconId), {
7243
+ size,
7244
+ color,
7245
+ className
7246
+ });
7247
+ }
7248
+ //#endregion
7140
7249
  //#region src/composites/confirm-dialog.tsx
7141
7250
  var ConfirmContext = createSharedContext("camstack:confirm-dialog", null);
7142
7251
  function useConfirm() {
@@ -19703,13 +19812,20 @@ function MultiSelectField({ field, value, onChange, disabled, translationFn }) {
19703
19812
  checked ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground hover:bg-surface",
19704
19813
  disabled || field.disabled ? "opacity-50 cursor-not-allowed" : ""
19705
19814
  ].join(" "),
19706
- children: [/* @__PURE__ */ jsx("input", {
19707
- type: "checkbox",
19708
- className: "sr-only",
19709
- checked,
19710
- disabled: disabled || field.disabled,
19711
- onChange: () => toggle(opt.value)
19712
- }), opt.label]
19815
+ children: [
19816
+ /* @__PURE__ */ jsx("input", {
19817
+ type: "checkbox",
19818
+ className: "sr-only",
19819
+ checked,
19820
+ disabled: disabled || field.disabled,
19821
+ onChange: () => toggle(opt.value)
19822
+ }),
19823
+ opt.iconId !== void 0 && /* @__PURE__ */ jsx(EventKindGlyph, {
19824
+ iconId: opt.iconId,
19825
+ size: 13
19826
+ }),
19827
+ opt.label
19828
+ ]
19713
19829
  }, opt.value);
19714
19830
  })
19715
19831
  })
@@ -21591,7 +21707,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21591
21707
  const resolutions = [...new Set(tier.options.map((o) => o.resolution))].sort((a, b) => (b ?? Infinity) - (a ?? Infinity));
21592
21708
  const selectedResolution = resolutions.includes(current?.resolution) ? current?.resolution : resolutions[0];
21593
21709
  const variantOptions = tier.options.filter((o) => o.resolution === selectedResolution);
21594
- const resLabel = (r) => r === void 0 ? "640 · native" : `${r}`;
21710
+ const resLabel = (r) => r === void 0 ? "native" : `${r}`;
21595
21711
  const selectTier = (tierId) => {
21596
21712
  const t = family.tiers.find((x) => x.tier === tierId);
21597
21713
  if (!t) return;
@@ -21635,7 +21751,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21635
21751
  className: "grid grid-cols-2 gap-1.5 sm:grid-cols-4",
21636
21752
  children: family.tiers.map((t) => {
21637
21753
  const active = t.tier === tier.tier;
21638
- const base = t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
21754
+ const quoted = t.options.find((o) => o.resolution === selectedResolution && o.precision === "fp32") ?? t.options.find((o) => o.modelId === t.baseModelId) ?? t.options[0];
21639
21755
  return /* @__PURE__ */ jsxs("button", {
21640
21756
  type: "button",
21641
21757
  disabled,
@@ -21651,7 +21767,7 @@ function GroupedModelSelector({ catalog, value, onChange, disabled }) {
21651
21767
  className: "text-[10px] text-foreground-subtle",
21652
21768
  children: [
21653
21769
  "~",
21654
- base?.sizeMB ?? 0,
21770
+ quoted?.sizeMB ?? 0,
21655
21771
  " MB"
21656
21772
  ]
21657
21773
  })]
@@ -21951,12 +22067,15 @@ function ConfigMultiSelect({ label, description, value, options, disabled, onCha
21951
22067
  /* @__PURE__ */ jsx("div", {
21952
22068
  className: "flex flex-wrap gap-1.5",
21953
22069
  children: options.map((o) => {
21954
- return /* @__PURE__ */ jsx("button", {
22070
+ return /* @__PURE__ */ jsxs("button", {
21955
22071
  type: "button",
21956
22072
  disabled,
21957
22073
  onClick: () => toggle(o.value),
21958
- className: cn("text-[10px] font-medium px-2 py-1 rounded-md border transition-colors", value.includes(o.value) ? "bg-primary/20 text-primary border-primary/40" : "bg-surface text-foreground-subtle border-border hover:border-primary/30", disabled && "opacity-50 cursor-not-allowed"),
21959
- children: o.label
22074
+ className: cn("inline-flex items-center gap-1 text-[10px] font-medium px-2 py-1 rounded-md border transition-colors", value.includes(o.value) ? "bg-primary/20 text-primary border-primary/40" : "bg-surface text-foreground-subtle border-border hover:border-primary/30", disabled && "opacity-50 cursor-not-allowed"),
22075
+ children: [o.iconId !== void 0 && /* @__PURE__ */ jsx(EventKindGlyph, {
22076
+ iconId: o.iconId,
22077
+ size: 12
22078
+ }), o.label]
21960
22079
  }, o.value);
21961
22080
  })
21962
22081
  })
@@ -44055,6 +44174,11 @@ function renderCellContent(state) {
44055
44174
  className: "font-mono text-foreground truncate",
44056
44175
  children: state.modelId
44057
44176
  }),
44177
+ state.clusterWide === true && /* @__PURE__ */ jsx("span", {
44178
+ className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-primary",
44179
+ title: "One value for the whole cluster — this step writes into a shared vector index",
44180
+ children: "cluster"
44181
+ }),
44058
44182
  state.jumpTo !== void 0 && /* @__PURE__ */ jsxs("span", {
44059
44183
  className: "ml-auto shrink-0 text-[8px] font-semibold text-sky-500",
44060
44184
  title: `runs on ${state.jumpTo}`,
@@ -44648,115 +44772,6 @@ function DoorbellRecentPanel({ history, limit = 5, latestIsFresh, className }) {
44648
44772
  });
44649
44773
  }
44650
44774
  //#endregion
44651
- //#region src/composites/event-kind-visuals.tsx
44652
- /**
44653
- * Event-kind VISUALS — the UI-side half of the unified taxonomy dictionary
44654
- * (`@camstack/types` `EVENT_TAXONOMY` owns the serializable data:
44655
- * color / iconId / labelKey; this owns `iconId → lucide component` and
44656
- * `labelKey → t()`).
44657
- *
44658
- * Every UI that renders an event kind (timeline, events tree, chips,
44659
- * detection canvas/tree) resolves its glyph + translated label here — no
44660
- * per-component hardcoded icon or label.
44661
- */
44662
- /**
44663
- * `iconId` → lucide component. Built ONLY from statically-imported icons
44664
- * (bundle-safe). Unknown ids resolve to the neutral `Tag` fallback.
44665
- */
44666
- var EVENT_KIND_ICONS = {
44667
- motion: Activity,
44668
- audio: Volume2,
44669
- person: User,
44670
- vehicle: Car,
44671
- animal: PawPrint,
44672
- package: Package,
44673
- sensor: Radio,
44674
- control: SlidersHorizontal,
44675
- car: Car,
44676
- truck: Truck,
44677
- bus: Bus,
44678
- motorcycle: Bike,
44679
- bicycle: Bike,
44680
- airplane: Plane,
44681
- boat: Sailboat,
44682
- train: TrainFront,
44683
- bird: Bird,
44684
- cat: Cat,
44685
- dog: Dog,
44686
- horse: PawPrint,
44687
- sheep: PawPrint,
44688
- cow: PawPrint,
44689
- elephant: PawPrint,
44690
- bear: PawPrint,
44691
- zebra: PawPrint,
44692
- giraffe: PawPrint,
44693
- door: DoorOpen,
44694
- pir: Radar,
44695
- smoke: Flame,
44696
- water: Droplet,
44697
- gas: Wind,
44698
- vibration: Vibrate,
44699
- tamper: ShieldAlert,
44700
- presence: UserCheck,
44701
- generic: Tag,
44702
- lock: Lock,
44703
- siren: Siren,
44704
- switch: ToggleRight,
44705
- doorbell: BellRing,
44706
- button: CircleDot,
44707
- "audio-speech": MessageSquare,
44708
- "audio-scream": Megaphone,
44709
- "audio-crying": Baby,
44710
- "audio-laughter": Laugh,
44711
- "audio-music": Music,
44712
- "audio-dog": Dog,
44713
- "audio-cat": Cat,
44714
- "audio-bird": Bird,
44715
- "audio-animal": PawPrint,
44716
- "audio-alarm": BellRing,
44717
- "audio-doorbell": BellRing,
44718
- "audio-glass_breaking": TriangleAlert,
44719
- "audio-gunshot": Crosshair,
44720
- "audio-vehicle": Car,
44721
- "audio-siren": Siren,
44722
- "audio-fire": Flame,
44723
- "audio-water": Droplets,
44724
- "audio-wind": Wind,
44725
- "audio-door": DoorOpen,
44726
- "audio-footsteps": Footprints,
44727
- "audio-crowd": Users,
44728
- "audio-telephone": Phone,
44729
- "audio-engine": Cog,
44730
- "audio-tools": Hammer,
44731
- "audio-silence": VolumeX
44732
- };
44733
- /** Resolve an `iconId` to a lucide component (falls back to `Tag`). */
44734
- function resolveEventKindIcon(iconId) {
44735
- if (Object.hasOwn(EVENT_KIND_ICONS, iconId)) return EVENT_KIND_ICONS[iconId];
44736
- if (iconId.startsWith("audio-")) return Volume2;
44737
- return Tag;
44738
- }
44739
- /**
44740
- * Translated label for an event kind — `t(labelKey)` when a translation
44741
- * exists, else the English `label` fallback. Robust to a missing key: an
44742
- * i18n backend that echoes the key unchanged (react-i18next default) is
44743
- * treated as "no translation" and the fallback label is returned, so the UI
44744
- * never renders a raw `eventKind.*` key.
44745
- */
44746
- function eventKindLabel(descriptor, t) {
44747
- if (t === void 0) return descriptor.label;
44748
- const translated = t(descriptor.labelKey);
44749
- return translated === descriptor.labelKey || translated.length === 0 ? descriptor.label : translated;
44750
- }
44751
- /** Small convenience component: renders the lucide glyph for an `iconId`. */
44752
- function EventKindGlyph({ iconId, size = 16, color, className }) {
44753
- return createElement(resolveEventKindIcon(iconId), {
44754
- size,
44755
- color,
44756
- className
44757
- });
44758
- }
44759
- //#endregion
44760
44775
  //#region src/composites/filter-bar.tsx
44761
44776
  function FilterBar({ filters, values, onChange, className }) {
44762
44777
  const isMobile = useIsMobile();
@@ -32,7 +32,7 @@ export declare function DialogTrigger({ children, ...props }: HTMLAttributes<HTM
32
32
  */
33
33
  declare const contentVariants: (props?: ({
34
34
  width?: "sm" | "md" | "lg" | null | undefined;
35
- scroll?: "content" | "body" | null | undefined;
35
+ scroll?: "body" | "content" | null | undefined;
36
36
  placement?: "center" | "sheet-on-mobile" | null | undefined;
37
37
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
38
38
  export type DialogPlacement = NonNullable<VariantProps<typeof contentVariants>['placement']>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/ui-library",
3
- "version": "1.2.62",
3
+ "version": "1.2.64",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",