@fluixi/devtools 0.2.0-alpha.5 → 0.2.0-alpha.7

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 (50) hide show
  1. package/dist/callsite.cjs +9 -0
  2. package/dist/callsite.d.ts.map +1 -1
  3. package/dist/callsite.js +9 -0
  4. package/dist/callsite.mjs +9 -0
  5. package/dist/export.cjs +1 -0
  6. package/dist/export.mjs +1 -0
  7. package/dist/graph-view.cjs +12 -3
  8. package/dist/graph-view.d.ts.map +1 -1
  9. package/dist/graph-view.js +11 -2
  10. package/dist/graph-view.mjs +12 -3
  11. package/dist/hook.cjs +173 -21
  12. package/dist/hook.mjs +174 -21
  13. package/dist/index.cjs +199 -29
  14. package/dist/index.mjs +200 -29
  15. package/dist/inspector.cjs +6 -2
  16. package/dist/inspector.js +1 -1
  17. package/dist/inspector.mjs +6 -2
  18. package/dist/instrument.cjs +9 -3
  19. package/dist/instrument.d.ts +16 -1
  20. package/dist/instrument.d.ts.map +1 -1
  21. package/dist/instrument.mjs +9 -3
  22. package/dist/kind-filter.cjs +5 -2
  23. package/dist/kind-filter.js +3 -3
  24. package/dist/kind-filter.mjs +5 -2
  25. package/dist/observe.cjs +172 -21
  26. package/dist/observe.d.ts.map +1 -1
  27. package/dist/observe.js +191 -22
  28. package/dist/observe.mjs +173 -21
  29. package/dist/palette.cjs +4 -1
  30. package/dist/palette.d.ts.map +1 -1
  31. package/dist/palette.js +3 -0
  32. package/dist/palette.mjs +4 -1
  33. package/dist/plugins/index.cjs +1 -1
  34. package/dist/plugins/index.mjs +1 -1
  35. package/dist/source.cjs +18 -3
  36. package/dist/source.d.ts +16 -1
  37. package/dist/source.d.ts.map +1 -1
  38. package/dist/source.js +25 -3
  39. package/dist/source.mjs +18 -3
  40. package/dist/tree.cjs +19 -4
  41. package/dist/tree.d.ts.map +1 -1
  42. package/dist/tree.js +21 -2
  43. package/dist/tree.mjs +19 -4
  44. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  45. package/dist/wire.cjs +3 -1
  46. package/dist/wire.d.ts +2 -0
  47. package/dist/wire.d.ts.map +1 -1
  48. package/dist/wire.js +2 -0
  49. package/dist/wire.mjs +3 -1
  50. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @fluixi/devtools v0.2.0-alpha.5 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/devtools v0.2.0-alpha.7 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -86,6 +86,7 @@ var import_store = require("@fluixi/reactive/store");
86
86
  // src/source.ts
87
87
  var MARKER = "__fx_source";
88
88
  var COMPONENT_MARKER = "__fx_component";
89
+ var CLASS_MARKER = "__fx_class";
89
90
  var HOLE_MARKER = "__fx_hole";
90
91
  var PROPS_MARKER = "__fx_props";
91
92
  var MARKS = "__FLUIXI_DEVTOOLS_MARKS__";
@@ -96,12 +97,16 @@ var shared = host[MARKS] ?? {
96
97
  components: /* @__PURE__ */ new Map()
97
98
  };
98
99
  host[MARKS] = shared;
99
- function markReactiveSource(file, line, column, name) {
100
+ shared.classes ??= /* @__PURE__ */ new WeakMap();
101
+ function markReactiveSource(file, line, column, name, self) {
100
102
  const location2 = locate(file, line, column);
101
103
  if (shared.pending && location2.external && !shared.pending.location?.external) return;
102
- shared.pending = { name, location: location2 };
104
+ shared.pending = self && typeof self === "object" ? { name, location: location2, self } : { name, location: location2 };
103
105
  shared.expiring = false;
104
106
  }
107
+ function dropReactiveSource() {
108
+ shared.pending = null;
109
+ }
105
110
  function locate(file, line, column) {
106
111
  const external = !!file && (/^([a-zA-Z]:)?[\\/]/.test(file) || file.includes("node_modules/"));
107
112
  return external ? { file, line, column, external } : { file, line, column };
@@ -115,13 +120,19 @@ function markComponentSource(name, file, line, column) {
115
120
  }
116
121
  if (!seen || seen.file !== file || seen.line !== line) shared.components.set(name, null);
117
122
  }
123
+ function markClassSource(constructor, file, line, column) {
124
+ if (typeof constructor === "function") shared.classes.set(constructor, locate(file, line, column));
125
+ }
126
+ function classSource(constructor) {
127
+ return typeof constructor === "function" ? shared.classes.get(constructor) : void 0;
128
+ }
118
129
  function componentSource(name) {
119
130
  return shared.components.get(name) ?? void 0;
120
131
  }
121
132
  function takeReactiveSource() {
122
133
  const mark = shared.pending;
123
134
  if (mark) {
124
- if (mark.name !== void 0) shared.pending = { location: mark.location };
135
+ if (mark.name !== void 0 || mark.self) shared.pending = { location: mark.location };
125
136
  if (!shared.expiring) {
126
137
  shared.expiring = true;
127
138
  queueMicrotask(() => {
@@ -161,6 +172,7 @@ function holeLocation(accessor) {
161
172
  function installSourceMarker() {
162
173
  if (typeof host[MARKER] !== "function") host[MARKER] = markReactiveSource;
163
174
  if (typeof host[COMPONENT_MARKER] !== "function") host[COMPONENT_MARKER] = markComponentSource;
175
+ if (typeof host[CLASS_MARKER] !== "function") host[CLASS_MARKER] = markClassSource;
164
176
  if (typeof host[HOLE_MARKER] !== "function") host[HOLE_MARKER] = markHole;
165
177
  if (typeof host[PROPS_MARKER] !== "function") host[PROPS_MARKER] = markProps;
166
178
  }
@@ -606,6 +618,15 @@ var INTERNAL = [
606
618
  "/packages/dom/",
607
619
  "/packages/core/",
608
620
  "/packages/devtools/",
621
+ "/packages/web-components/",
622
+ "/packages/auth/",
623
+ "/packages/oauth2/",
624
+ "/packages/session/",
625
+ "/packages/router/",
626
+ "/packages/head/",
627
+ "/packages/start/",
628
+ "/packages/server/",
629
+ "/packages/template-runtime/",
609
630
  "/@fluixi/",
610
631
  "node_modules",
611
632
  "fluixi-devtools",
@@ -1098,7 +1119,10 @@ var KIND_COLOR = {
1098
1119
  binding: "#5eead4",
1099
1120
  setter: "#fb7185",
1100
1121
  group: "#8a90a2",
1101
- element: "#8a90a2"
1122
+ element: "#8a90a2",
1123
+ "custom-element": "#2dd4bf",
1124
+ module: "#facc15",
1125
+ service: "#60a5fa"
1102
1126
  };
1103
1127
  var kindVar = (kind) => `--fx-kind-${kind}`;
1104
1128
  var kindColor = (kind) => `var(${kindVar(kind)}, ${KIND_COLOR[kind]})`;
@@ -1115,7 +1139,11 @@ var TREE_KINDS = /* @__PURE__ */ new Set([
1115
1139
  "handler",
1116
1140
  // A component a plugin recognised as providing a context. Still a tag the author wrote,
1117
1141
  // so leaving it out took it and everything it rendered out of the tree.
1118
- "provider"
1142
+ "provider",
1143
+ // Scopes the runtime reported: what their signals and memos belong to.
1144
+ "custom-element",
1145
+ "module",
1146
+ "service"
1119
1147
  ]);
1120
1148
  function inPageOrder(nodes) {
1121
1149
  const slots = [];
@@ -1138,7 +1166,8 @@ function badgeOf(node) {
1138
1166
  return badges.get(node);
1139
1167
  }
1140
1168
  function componentTree(graph, options = {}) {
1141
- const wanted = (node) => TREE_KINDS.has(node.kind) || options.values === true && node.authored !== false;
1169
+ const held = (node) => node.scope !== void 0 && (node.kind === "state" || node.kind === "memo" || node.kind === "store");
1170
+ const wanted = (node) => TREE_KINDS.has(node.kind) || options.values === true && (node.authored !== false || held(node));
1142
1171
  const tagged = inPageOrder([...graph.values()].filter(wanted).sort((a, b) => a.id - b.id));
1143
1172
  const made = /* @__PURE__ */ new Map();
1144
1173
  for (const node of tagged) {
@@ -1334,7 +1363,8 @@ function createComponentTree(host2, options = {}) {
1334
1363
  const props = listed.length ? [{ key: group, label: "props", kind: node.kind, children: listed, props: true, owner: node.id }] : [];
1335
1364
  const row2 = {
1336
1365
  key: String(node.id),
1337
- label: node.label,
1366
+ // `<fx-counter>` in the graph, where nothing else draws brackets. Here the row adds them.
1367
+ label: node.kind === "custom-element" ? node.label.replace(/^<(.*)>$/, "$1") : node.label,
1338
1368
  kind: node.kind,
1339
1369
  id: node.id,
1340
1370
  children: [...props, ...node.children.map(build2)],
@@ -1453,6 +1483,12 @@ function createComponentTree(host2, options = {}) {
1453
1483
  };
1454
1484
  }
1455
1485
  const rendered = dom.map((node, i) => walk2(node, `${row2.id}:${i}`)).filter((node) => node !== void 0);
1486
+ const self = rendered[0];
1487
+ if (row2.kind === "custom-element" && rendered.length === 1 && self?.kind === "element") {
1488
+ rendered.splice(0, 1, ...self.children);
1489
+ if (self.element) row2.element = self.element;
1490
+ if (self.at) row2.at = self.at;
1491
+ }
1456
1492
  const rest = row2.children.filter((child) => !placed.has(child)).map(expand);
1457
1493
  const lifted = [];
1458
1494
  const spare = [];
@@ -1629,9 +1665,14 @@ var PREFIX = {
1629
1665
  // A plugin's, and it names them itself.
1630
1666
  directive: "d",
1631
1667
  context: "ctx",
1632
- provider: "p"
1668
+ provider: "p",
1669
+ // Scopes are always named by what opened them.
1670
+ "custom-element": "el",
1671
+ module: "mod",
1672
+ service: "svc"
1633
1673
  };
1634
1674
  function readProps(props) {
1675
+ if (readOnce.has(props)) return readOnce.get(props);
1635
1676
  const at3 = propsLocations(props);
1636
1677
  const out = [];
1637
1678
  for (const name of Object.keys(props)) {
@@ -1642,13 +1683,25 @@ function readProps(props) {
1642
1683
  ...where ? { at: { line: where[0], column: where[1] } } : {}
1643
1684
  };
1644
1685
  try {
1645
- report.value = formatValue((0, import_signal2.untrack)(() => props[name]), 200);
1686
+ report.value = formatValue(
1687
+ (0, import_signal2.createRoot)((dispose) => {
1688
+ try {
1689
+ return (0, import_signal2.untrack)(() => props[name]);
1690
+ } finally {
1691
+ dispose();
1692
+ }
1693
+ }),
1694
+ 200
1695
+ );
1646
1696
  } catch {
1647
1697
  }
1648
1698
  out.push(report);
1649
1699
  }
1650
- return out.length ? out : void 0;
1700
+ const reports = out.length ? out : void 0;
1701
+ readOnce.set(props, reports);
1702
+ return reports;
1651
1703
  }
1704
+ var readOnce = /* @__PURE__ */ new WeakMap();
1652
1705
  function observeGraph(options = {}) {
1653
1706
  installSourceMarker();
1654
1707
  const origin = options.origin ?? (typeof location === "object" ? location.origin : void 0);
@@ -1669,6 +1722,10 @@ function observeGraph(options = {}) {
1669
1722
  const boundTo = /* @__PURE__ */ new WeakMap();
1670
1723
  const drivenBy = /* @__PURE__ */ new WeakMap();
1671
1724
  let reaches2 = /* @__PURE__ */ new Map();
1725
+ const SCOPE_KINDS = /* @__PURE__ */ new Set(["custom-element", "module", "service"]);
1726
+ const scopeIds = /* @__PURE__ */ new WeakMap();
1727
+ const scopeOfTarget = /* @__PURE__ */ new WeakMap();
1728
+ const fieldsOf = /* @__PURE__ */ new WeakMap();
1672
1729
  let described = null;
1673
1730
  const rendered = /* @__PURE__ */ new Map();
1674
1731
  const elementsIn = (value) => {
@@ -1765,7 +1822,9 @@ function observeGraph(options = {}) {
1765
1822
  // Mapped, unlike `mark`: these two came off a stack, so they are positions in the
1766
1823
  // compiled file until a host translates them.
1767
1824
  ...site && !site.external ? { usedAt: mapped(site.location) } : {},
1768
- ...site && site.external && !mark?.location ? { source: mapped(site.location) } : {}
1825
+ // Not inside a scope: an element's prop is made by the package for the element, and
1826
+ // the package's line says less than the scope it sits in already does.
1827
+ ...site && site.external && !mark?.location && !report.scope ? { source: mapped(site.location) } : {}
1769
1828
  };
1770
1829
  const owner = ancestor(report.parents);
1771
1830
  if (owner !== void 0) node.createdIn = owner;
@@ -1775,6 +1834,28 @@ function observeGraph(options = {}) {
1775
1834
  node.createdIn = originId;
1776
1835
  if (from.source) node.source = from.source;
1777
1836
  }
1837
+ const scopeId = report.scope ? scopeIds.get(report.scope) : void 0;
1838
+ if (scopeId !== void 0) {
1839
+ node.scope = scopeId;
1840
+ const creator = node.createdIn !== void 0 ? graph.get(node.createdIn) : void 0;
1841
+ const insideAlready = node.createdIn === scopeId || creator?.scope === scopeId;
1842
+ if (!insideAlready) node.createdIn = scopeId;
1843
+ } else if (node.createdIn !== void 0) {
1844
+ const creator = graph.get(node.createdIn);
1845
+ const inherited = creator && SCOPE_KINDS.has(creator.kind) ? creator.id : creator?.scope;
1846
+ if (inherited !== void 0) node.scope = inherited;
1847
+ }
1848
+ const self = mark?.self;
1849
+ if (self) {
1850
+ const list = fieldsOf.get(self);
1851
+ if (list) list.push(id);
1852
+ else fieldsOf.set(self, [id]);
1853
+ const open = scopeOfTarget.get(self);
1854
+ if (open !== void 0 && graph.has(open)) {
1855
+ node.scope = open;
1856
+ node.createdIn = open;
1857
+ }
1858
+ }
1778
1859
  if (kind !== "effect" && typeof handle === "function") {
1779
1860
  const read = handle;
1780
1861
  node.read = () => (0, import_signal2.untrack)(read);
@@ -1910,20 +1991,90 @@ function observeGraph(options = {}) {
1910
1991
  internals.delete(target);
1911
1992
  const id = ids.get(target);
1912
1993
  if (id === void 0) return;
1913
- removed.push({ id, rev: ++revision });
1914
- revs.delete(id);
1915
- if (removed.length > REMOVED_LOG) removed.splice(0, removed.length - REMOVED_LOG);
1916
- history.disposed(id, graph.get(id)?.label);
1917
- graph.delete(id);
1918
- handed.delete(id);
1919
- raws.delete(id);
1920
- cores.delete(id);
1921
- rendered.delete(id);
1922
- setters.delete(id);
1923
- runsAtLastSample.delete(id);
1924
- unnamed.delete(id);
1994
+ forget(id);
1995
+ },
1996
+ scope(scope, info, parent) {
1997
+ dropReactiveSource();
1998
+ const id = seq++;
1999
+ const kind = info.kind === "element" ? "custom-element" : info.kind;
2000
+ const parentId = parent ? scopeIds.get(parent) : void 0;
2001
+ const found = currentCallSite(origin);
2002
+ const site = found && !/\0|__x00__|^virtual:/.test(found.location.file ?? "") ? found : void 0;
2003
+ const node = {
2004
+ id,
2005
+ label: info.name,
2006
+ kind,
2007
+ // The author named the element, the module and the service; none of them is plumbing.
2008
+ authored: true,
2009
+ deps: /* @__PURE__ */ new Set(),
2010
+ writes: /* @__PURE__ */ new Set(),
2011
+ runs: 0,
2012
+ lastPulse: 0,
2013
+ ...info.detail ? { value: info.detail, detail: info.detail } : {},
2014
+ ...parentId !== void 0 ? { scope: parentId, createdIn: parentId } : {}
2015
+ };
2016
+ const target = info.target;
2017
+ if (kind === "custom-element") {
2018
+ const defined = target ? classSource(target.constructor) : void 0;
2019
+ if (defined) node.declaredAt = defined;
2020
+ } else if (site && !site.external) {
2021
+ node.usedAt = mapped(site.location);
2022
+ }
2023
+ scopeIds.set(scope, id);
2024
+ if (target && typeof target === "object" && target.nodeType === 1) {
2025
+ rendered.set(id, [new WeakRef(target)]);
2026
+ }
2027
+ graph.set(id, node);
2028
+ history.created(id, node.createdIn, node.label);
2029
+ if (target && typeof target === "object") {
2030
+ scopeOfTarget.set(target, id);
2031
+ for (const field of fieldsOf.get(target) ?? []) {
2032
+ const made = graph.get(field);
2033
+ if (!made) continue;
2034
+ made.scope = id;
2035
+ made.createdIn = id;
2036
+ revs.set(field, ++revision);
2037
+ }
2038
+ }
2039
+ },
2040
+ scopeEnded(scope) {
2041
+ const id = scopeIds.get(scope);
2042
+ if (id === void 0) return;
2043
+ const ended = /* @__PURE__ */ new Set([id]);
2044
+ for (let grew = true; grew; ) {
2045
+ grew = false;
2046
+ for (const [other, node] of graph) {
2047
+ if (!ended.has(other) && node.scope !== void 0 && ended.has(node.scope)) {
2048
+ ended.add(other);
2049
+ grew = true;
2050
+ }
2051
+ }
2052
+ }
2053
+ for (const gone of ended) forget(gone);
2054
+ },
2055
+ scopeAdopted(scope, parent) {
2056
+ const node = graph.get(scopeIds.get(scope) ?? -1);
2057
+ const parentId = scopeIds.get(parent);
2058
+ if (!node || parentId === void 0 || parentId === node.id) return;
2059
+ node.scope = parentId;
2060
+ node.createdIn = parentId;
2061
+ revs.set(node.id, ++revision);
1925
2062
  }
1926
2063
  });
2064
+ function forget(id) {
2065
+ removed.push({ id, rev: ++revision });
2066
+ revs.delete(id);
2067
+ if (removed.length > REMOVED_LOG) removed.splice(0, removed.length - REMOVED_LOG);
2068
+ history.disposed(id, graph.get(id)?.label);
2069
+ graph.delete(id);
2070
+ handed.delete(id);
2071
+ raws.delete(id);
2072
+ cores.delete(id);
2073
+ rendered.delete(id);
2074
+ setters.delete(id);
2075
+ runsAtLastSample.delete(id);
2076
+ unnamed.delete(id);
2077
+ }
1927
2078
  const edges = (id, node) => {
1928
2079
  const sources = cores.get(id)?.sources;
1929
2080
  node.deps.clear();
@@ -1943,6 +2094,14 @@ function observeGraph(options = {}) {
1943
2094
  revs.set(id, ++revision);
1944
2095
  };
1945
2096
  const now = Date.now();
2097
+ for (const [id, node] of graph) {
2098
+ if (node.kind !== "custom-element" || node.usedAt) continue;
2099
+ const element = rendered.get(id)?.[0]?.deref();
2100
+ const written = element ? element.__fx_loc : void 0;
2101
+ if (!written?.file) continue;
2102
+ node.usedAt = { file: written.file, line: written.line, column: written.column };
2103
+ revs.set(id, ++revision);
2104
+ }
1946
2105
  const bindings = /* @__PURE__ */ new Map();
1947
2106
  const drives = /* @__PURE__ */ new Map();
1948
2107
  const seen = /* @__PURE__ */ new Map();
@@ -2328,6 +2487,7 @@ function serializeGraph(graph, now = Date.now(), options = {}) {
2328
2487
  declaredAt: node.declaredAt,
2329
2488
  usedAt: node.usedAt,
2330
2489
  createdIn: node.createdIn,
2490
+ scope: node.scope,
2331
2491
  bindings: node.bindings,
2332
2492
  targets: node.targets,
2333
2493
  setAt: node.setAt,
@@ -2365,6 +2525,7 @@ function snapshotToRenderMap(snapshot) {
2365
2525
  declaredAt: node.declaredAt,
2366
2526
  usedAt: node.usedAt,
2367
2527
  createdIn: node.createdIn,
2528
+ scope: node.scope,
2368
2529
  bindings: node.bindings,
2369
2530
  targets: node.targets,
2370
2531
  setAt: node.setAt,
@@ -2517,8 +2678,8 @@ var OVER_NATURAL = 12;
2517
2678
  var MIN_MAX_ZOOM = 8;
2518
2679
  var ABSOLUTE_MAX_ZOOM = 4e3;
2519
2680
  var DRAG_SLOP = 4;
2520
- var KIND_CLASS = { state: "n-state", memo: "n-memo", effect: "n-effect", store: "n-store", resource: "n-resource", component: "n-component", control: "n-control", router: "n-router", handler: "n-handler", group: "n-group", binding: "n-binding", setter: "n-setter", directive: "n-directive", context: "n-context", provider: "n-provider" };
2521
- var KIND_GLYPH = { state: "◆ state", memo: "ƒ memo", effect: "⚡ effect", store: "▤ store", resource: "⟳ resource", component: "◧ component", control: "⑂ control flow", router: "⤳ router", handler: "⇄ route", group: "▤ framework", binding: "⇥ dom", setter: "✎ sets", directive: "⌘ directive", context: "◈ context", provider: "◈ provider" };
2681
+ var KIND_CLASS = { state: "n-state", memo: "n-memo", effect: "n-effect", store: "n-store", resource: "n-resource", component: "n-component", control: "n-control", router: "n-router", handler: "n-handler", group: "n-group", binding: "n-binding", setter: "n-setter", directive: "n-directive", context: "n-context", provider: "n-provider", "custom-element": "n-custom-element", module: "n-module", service: "n-service" };
2682
+ var KIND_GLYPH = { state: "◆ state", memo: "ƒ memo", effect: "⚡ effect", store: "▤ store", resource: "⟳ resource", component: "◧ component", control: "⑂ control flow", router: "⤳ router", handler: "⇄ route", group: "▤ framework", binding: "⇥ dom", setter: "✎ sets", directive: "⌘ directive", context: "◈ context", provider: "◈ provider", "custom-element": "⬡ custom element", module: "▦ module", service: "⚙ service" };
2522
2683
  var GROUP_ID = -1;
2523
2684
  var bindingIds = /* @__PURE__ */ new Map();
2524
2685
  var bindingId = (place2) => {
@@ -2779,6 +2940,7 @@ function createGraphView(svg, options = {}) {
2779
2940
  const inProject = (at3) => !!at3?.file && at3.external !== true;
2780
2941
  const machinery = (n) => {
2781
2942
  if (n.authored !== false) return false;
2943
+ if (n.scope !== void 0) return false;
2782
2944
  if (n.kind === "state" || n.kind === "memo" || n.kind === "effect" || n.kind === "context") {
2783
2945
  return true;
2784
2946
  }
@@ -3188,6 +3350,11 @@ ${kindRules((k) => `.fx-node.n-${k}`, "--glow")}
3188
3350
  .fx-node.n-binding { opacity: .72; }
3189
3351
  .fx-node.n-setter { opacity: .72; }
3190
3352
  .fx-node.n-binding .fx-box, .fx-node.n-setter .fx-box { stroke-dasharray: 3 3; }
3353
+ /* An element, module or service: a group its signals and memos belong to, so it reads as one. */
3354
+ .fx-node.n-custom-element .fx-box, .fx-node.n-module .fx-box, .fx-node.n-service .fx-box {
3355
+ stroke-width: 2.2;
3356
+ fill: color-mix(in oklab, var(--glow, #5eead4) 14%, var(--fx-node-bg, #131722));
3357
+ }
3191
3358
  .fx-node.n-external { opacity: .55; }
3192
3359
  .fx-node.n-external .fx-box { stroke-dasharray: 3 2; }
3193
3360
  .fx-box { fill: var(--fx-node-bg, #131722); stroke: var(--glow, #5eead4); stroke-width: 1.4; stroke-opacity: calc(.5 + var(--pulse,0) * .5); }
@@ -3646,7 +3813,7 @@ function createInspector(host2, options = {}) {
3646
3813
  // no locations at all, and an empty line there reads as missing data.
3647
3814
  (node.source ? `<div class="ins-source">${node.source.external ? "📦" : "📍"} ${place(bothAt(node.source, root), node.source, reveals)}</div>` : "") + // A component is created where its tag is written; where it is declared is somewhere
3648
3815
  // else, and only worth a line when it is.
3649
- (node.declaredAt && at(node.declaredAt, root) !== at(node.source, root) ? `<div class="ins-source">◧ declared ${place(at(node.declaredAt, root), node.declaredAt, reveals)}</div>` : "") + // A node a package made on the application's behalf: the package's line is where it
3816
+ (node.declaredAt && at(node.declaredAt, root) !== at(node.source, root) ? `<div class="ins-source">◧ ${node.kind === "custom-element" ? "defined at" : "declared"} ${place(at(node.declaredAt, root), node.declaredAt, reveals)}</div>` : "") + // A node a package made on the application's behalf: the package's line is where it
3650
3817
  // was created, and this is the line that asked for it.
3651
3818
  (node.usedAt ? `<div class="ins-source">↗ used at ${place(bothAt(node.usedAt, root), node.usedAt, reveals)}</div>` : "") + // Nothing said where it came from at all: the compiler did not mark this project and
3652
3819
  // the stack had nothing to offer either. Saying so beats a card that just sits there.
@@ -4059,9 +4226,12 @@ var FILTERABLE_KINDS = [
4059
4226
  "router",
4060
4227
  "handler",
4061
4228
  "context",
4062
- "directive"
4229
+ "directive",
4230
+ "custom-element",
4231
+ "module",
4232
+ "service"
4063
4233
  ];
4064
- var LABEL = { handler: "route" };
4234
+ var LABEL = { handler: "route", "custom-element": "custom element" };
4065
4235
  function createKindFilter(host2, options) {
4066
4236
  const doc = host2.ownerDocument;
4067
4237
  const kinds = options.kinds ?? FILTERABLE_KINDS;