@spaethtech/svelte-ui 0.21.1-dev.128.59d3487 → 0.21.1-dev.130.6593aa4

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/CLAUDE.md CHANGED
@@ -162,9 +162,21 @@ host port). Get its IP with `docker inspect svelte-ui-demo-1 --format '{{range .
162
162
  (`svelte-ui-caddy-1` proxies to it; `php-svelte.spaethtech.dev` → the host `:5173`). `curl` the route
163
163
  first to confirm it serves, then point a browser at it.
164
164
 
165
+ **For INTERACTION / HYDRATION testing, use the Caddy route `https://svelte-ui.spaethtech.dev/<route>`
166
+ (Playwright `ignoreHTTPSErrors: true`), NOT the container IP.** Hitting the container IP `:5173`
167
+ directly serves the SSR HTML but **intermittently fails to hydrate**: vite's HMR client tries
168
+ `ws://<ip>:443` (refused) and the route's dynamic client module then fails to fetch, so the page stays
169
+ SSR-only and **all client interactivity is dead** — clicks/keyboard/`bind:`/`oninput` do nothing, and a
170
+ Svelte `.fill()` won't propagate to bound state. This looks exactly like a component bug but isn't; it
171
+ bit this project's DatePicker2-reset and Tree-lazy verifications. The Caddy origin terminates TLS on
172
+ `:443`, so HMR + module imports load and the page hydrates reliably. Container IP is fine for
173
+ **SSR-only / visual** checks (screenshots of rendered markup); use Caddy whenever you click, type, or
174
+ assert post-hydration state. Confirm hydration first (e.g. toggle a known control and see state flip)
175
+ before trusting an interaction result — don't report "verified" from a page that never hydrated.
176
+
165
177
  Use the **`/playwright-cli`** workflow for browser-driven testing (navigation, snapshots/screenshots,
166
- console inspection, interaction). Point it at the **container IP** `:5173` and the relevant demo route
167
- (e.g. `/tabstrip`). The old Chrome DevTools MCP (`.mcp.json` + `chrome-devtools-mcp`) has been removed
178
+ console inspection, interaction). Point it at the **Caddy route** for interaction (container IP only for
179
+ SSR/visual) and the relevant demo route (e.g. `/tabstrip`). The old Chrome DevTools MCP (`.mcp.json` + `chrome-devtools-mcp`) has been removed
168
180
  in favor of this. **Browser-binary gotcha:** the Playwright in `node_modules` and the cached browser
169
181
  revision can mismatch (e.g. it wants `headless_shell-1181` but the cache has `chromium-1229`); pass
170
182
  `executablePath` to the installed `~/.cache/ms-playwright/chromium-*/chrome-linux64/chrome` instead of
@@ -23,7 +23,10 @@
23
23
  children,
24
24
  ...rest
25
25
  }: {
26
- items: MenuItem[];
26
+ /** The menu items — a static list, OR a function of the triggering event so one wrapper can build
27
+ * the menu from whatever was right-clicked (read `event.target`, a row's `data-key`, …) without
28
+ * the consumer tracking target state during the bubble. Return `[]` to suppress the menu. */
29
+ items: MenuItem[] | ((event: MouseEvent) => MenuItem[]);
27
30
  size?: Responsive<Size>;
28
31
  variant?: Variant;
29
32
  disabled?: boolean;
@@ -35,10 +38,14 @@
35
38
  let anchorEl = $state<HTMLElement>();
36
39
  let x = $state(0);
37
40
  let y = $state(0);
41
+ // The items shown for the current open — a snapshot (for the function form, computed from the event).
42
+ let resolvedItems = $state<MenuItem[]>([]);
38
43
 
39
44
  function onContextMenu(e: MouseEvent) {
40
45
  if (disabled) return;
41
46
  e.preventDefault();
47
+ resolvedItems = typeof items === "function" ? items(e) : items;
48
+ if (!resolvedItems?.length) return; // nothing to show → don't open (and let no empty menu flash)
42
49
  x = e.clientX;
43
50
  y = e.clientY;
44
51
  open = true;
@@ -57,4 +64,4 @@
57
64
  style="position: fixed; left: {x}px; top: {y}px; width: 0; height: 0; pointer-events: none;"
58
65
  ></span>
59
66
 
60
- <Menu anchor={anchorEl} bind:open {items} {size} {variant} side="bottom" align="start" />
67
+ <Menu anchor={anchorEl} bind:open items={resolvedItems} {size} {variant} side="bottom" align="start" />
@@ -5,7 +5,10 @@ import type { Variant } from "../../types/variants.js";
5
5
  import type { Size } from "../../types/sizes.js";
6
6
  import type { Responsive } from "../../types/responsive.js";
7
7
  type $$ComponentProps = {
8
- items: MenuItem[];
8
+ /** The menu items — a static list, OR a function of the triggering event so one wrapper can build
9
+ * the menu from whatever was right-clicked (read `event.target`, a row's `data-key`, …) without
10
+ * the consumer tracking target state during the bubble. Return `[]` to suppress the menu. */
11
+ items: MenuItem[] | ((event: MouseEvent) => MenuItem[]);
9
12
  size?: Responsive<Size>;
10
13
  variant?: Variant;
11
14
  disabled?: boolean;
@@ -256,6 +256,7 @@
256
256
  bind:this={rowRefs[f.key]}
257
257
  role="treeitem"
258
258
  data-key={f.key}
259
+ aria-label={f.node.label}
259
260
  aria-level={f.level + 1}
260
261
  aria-selected={active}
261
262
  aria-expanded={f.hasChildren ? f.open : undefined}
@@ -840,8 +840,11 @@ Vertical event sequence — marker + connecting line + title/time/description.
840
840
  Right-click menu over any content; opens `Menu` at the pointer.
841
841
 
842
842
  - **Location**: `src/lib/components/ContextMenu/ContextMenu.svelte`
843
- - **Props**: `items` (`MenuItem[]`), `size`, `variant`, `disabled` (leaves the native menu), `class`,
844
- `children` (the right-clickable content)
843
+ - **Props**: `items` (`MenuItem[]` **or** `(event: MouseEvent) => MenuItem[]`), `size`, `variant`,
844
+ `disabled` (leaves the native menu), `class`, `children` (the right-clickable content)
845
+ - **Dynamic items**: pass a function to build the menu from whatever was right-clicked — read
846
+ `event.target` (e.g. a row's `data-key`) and return that target's items; return `[]` to suppress the
847
+ menu. Lets one wrapper serve many targets (e.g. a `Tree`/file list) without tracking target state.
845
848
  - **Composition**: `Menu` anchored to a 0-size point at the pointer; flips/shifts at edges
846
849
 
847
850
  ### Tree
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaethtech/svelte-ui",
3
- "version": "0.21.1-dev.128.59d3487",
3
+ "version": "0.21.1-dev.130.6593aa4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/spaethtech/svelte-ui.git"