@poodle64/ui 2026.9.18 → 2026.9.19
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.
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
2
|
export interface Fact {
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Stable identity for #each; never rendered. Also the id bound through
|
|
5
|
+
* `activeFactId`/`focusedFactId` — a consumer keys this the same way it
|
|
6
|
+
* keys the matching `PageCanvasRegion.id`, so the two lists share one
|
|
7
|
+
* key space and a single pair of bound variables ties a fact to where
|
|
8
|
+
* it is printed.
|
|
9
|
+
*/
|
|
4
10
|
key: string;
|
|
5
11
|
/** Uppercase eyebrow label. */
|
|
6
12
|
label: string;
|
|
@@ -8,6 +14,12 @@
|
|
|
8
14
|
value: string;
|
|
9
15
|
/** Render the value in the figures' face: mono, tabular. */
|
|
10
16
|
numeric?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* This fact was actually placed somewhere on the page. Only then does
|
|
19
|
+
* it become pointable (hoverable, focusable, clickable); absent or
|
|
20
|
+
* false renders it as plain text, never a control that does nothing.
|
|
21
|
+
*/
|
|
22
|
+
hasEvidence?: boolean;
|
|
11
23
|
}
|
|
12
24
|
</script>
|
|
13
25
|
|
|
@@ -21,18 +33,41 @@
|
|
|
21
33
|
// a titled card for the context column; reach for FactGrid instead where
|
|
22
34
|
// a Panel or DetailPanel already supplies the box, so nesting never
|
|
23
35
|
// doubles the border (godswood's FactGrid stop-gap, #839).
|
|
36
|
+
//
|
|
37
|
+
// An evidenced fact ties to its place on the page exactly as PageCanvas's
|
|
38
|
+
// own region list does: `activeFactId` mirrors `activeRegionId` (hover or
|
|
39
|
+
// keyboard focus), `focusedFactId` mirrors `focusedRegionId` (click, held
|
|
40
|
+
// until clicked again). A consumer binds both pairs to the same two
|
|
41
|
+
// variables — nothing FactGrid-specific lives here, it only reports and
|
|
42
|
+
// accepts the same two ids PageCanvas already reads (#839).
|
|
24
43
|
let {
|
|
25
44
|
facts,
|
|
45
|
+
activeFactId = $bindable(null),
|
|
46
|
+
focusedFactId = $bindable(null),
|
|
26
47
|
class: klass = '',
|
|
27
48
|
ref = $bindable(null),
|
|
28
49
|
...restProps
|
|
29
50
|
}: WithElementRef<HTMLAttributes<HTMLElement>> & {
|
|
30
51
|
facts: Fact[];
|
|
52
|
+
/** Hovered or keyboard-focused; mirrors PageCanvas's `activeRegionId`. */
|
|
53
|
+
activeFactId?: string | null;
|
|
54
|
+
/** Clicked, held until clicked again; mirrors `focusedRegionId`. */
|
|
55
|
+
focusedFactId?: string | null;
|
|
31
56
|
} = $props();
|
|
32
57
|
|
|
33
58
|
// A sentence takes the whole row; a short value shares it with its
|
|
34
59
|
// neighbours. 40 is the length the source stop-gap measured this against.
|
|
35
60
|
const LONG_VALUE = 40;
|
|
61
|
+
|
|
62
|
+
function setActive(key: string) {
|
|
63
|
+
activeFactId = key;
|
|
64
|
+
}
|
|
65
|
+
function clearActive(key: string) {
|
|
66
|
+
if (activeFactId === key) activeFactId = null;
|
|
67
|
+
}
|
|
68
|
+
function toggleFocus(key: string) {
|
|
69
|
+
focusedFactId = focusedFactId === key ? null : key;
|
|
70
|
+
}
|
|
36
71
|
</script>
|
|
37
72
|
|
|
38
73
|
<dl
|
|
@@ -46,7 +81,26 @@
|
|
|
46
81
|
{fact.label}
|
|
47
82
|
</dt>
|
|
48
83
|
<dd class={cn('mt-1 break-words', fact.numeric && 'font-mono tabular-nums')}>
|
|
49
|
-
{fact.
|
|
84
|
+
{#if fact.hasEvidence}
|
|
85
|
+
<button
|
|
86
|
+
type="button"
|
|
87
|
+
class={cn(
|
|
88
|
+
'-mx-0.5 block w-full rounded-sm px-0.5 text-left underline decoration-transparent underline-offset-2 transition-colors hover:decoration-current focus-visible:decoration-current focus-visible:outline-none',
|
|
89
|
+
(activeFactId === fact.key || focusedFactId === fact.key) &&
|
|
90
|
+
'bg-primary/10 text-primary decoration-current'
|
|
91
|
+
)}
|
|
92
|
+
aria-pressed={focusedFactId === fact.key}
|
|
93
|
+
onmouseenter={() => setActive(fact.key)}
|
|
94
|
+
onmouseleave={() => clearActive(fact.key)}
|
|
95
|
+
onfocus={() => setActive(fact.key)}
|
|
96
|
+
onblur={() => clearActive(fact.key)}
|
|
97
|
+
onclick={() => toggleFocus(fact.key)}
|
|
98
|
+
>
|
|
99
|
+
{fact.value}
|
|
100
|
+
</button>
|
|
101
|
+
{:else}
|
|
102
|
+
{fact.value}
|
|
103
|
+
{/if}
|
|
50
104
|
</dd>
|
|
51
105
|
</div>
|
|
52
106
|
{/each}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export interface Fact {
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Stable identity for #each; never rendered. Also the id bound through
|
|
4
|
+
* `activeFactId`/`focusedFactId` — a consumer keys this the same way it
|
|
5
|
+
* keys the matching `PageCanvasRegion.id`, so the two lists share one
|
|
6
|
+
* key space and a single pair of bound variables ties a fact to where
|
|
7
|
+
* it is printed.
|
|
8
|
+
*/
|
|
3
9
|
key: string;
|
|
4
10
|
/** Uppercase eyebrow label. */
|
|
5
11
|
label: string;
|
|
@@ -7,12 +13,22 @@ export interface Fact {
|
|
|
7
13
|
value: string;
|
|
8
14
|
/** Render the value in the figures' face: mono, tabular. */
|
|
9
15
|
numeric?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* This fact was actually placed somewhere on the page. Only then does
|
|
18
|
+
* it become pointable (hoverable, focusable, clickable); absent or
|
|
19
|
+
* false renders it as plain text, never a control that does nothing.
|
|
20
|
+
*/
|
|
21
|
+
hasEvidence?: boolean;
|
|
10
22
|
}
|
|
11
23
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
12
24
|
import { type WithElementRef } from '../../../utils.js';
|
|
13
25
|
type $$ComponentProps = WithElementRef<HTMLAttributes<HTMLElement>> & {
|
|
14
26
|
facts: Fact[];
|
|
27
|
+
/** Hovered or keyboard-focused; mirrors PageCanvas's `activeRegionId`. */
|
|
28
|
+
activeFactId?: string | null;
|
|
29
|
+
/** Clicked, held until clicked again; mirrors `focusedRegionId`. */
|
|
30
|
+
focusedFactId?: string | null;
|
|
15
31
|
};
|
|
16
|
-
declare const FactGrid: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
32
|
+
declare const FactGrid: import("svelte").Component<$$ComponentProps, {}, "ref" | "activeFactId" | "focusedFactId">;
|
|
17
33
|
type FactGrid = ReturnType<typeof FactGrid>;
|
|
18
34
|
export default FactGrid;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poodle64/ui",
|
|
3
|
-
"version": "2026.9.
|
|
3
|
+
"version": "2026.9.19",
|
|
4
4
|
"description": "Household shared component layer: shadcn-svelte primitives (bits-ui) plus the composed page chrome every app builds its routes from, restyled by each app's @poodle64/design-tokens alias layer. One fix reaches every app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @poodle64/ui — situation → component map
|
|
2
2
|
|
|
3
3
|
<!-- GENERATED by scripts/generate-registry.mjs from scripts/situations.json + package source. DO NOT EDIT. -->
|
|
4
|
-
Generated from `@poodle64/ui@2026.9.
|
|
4
|
+
Generated from `@poodle64/ui@2026.9.19`. 60 components, 17 situations.
|
|
5
5
|
|
|
6
6
|
**Read this before writing a `<div>`.** Find the SITUATION you are in below, then compose the component named for it — do not hand-build it from raw `Card` or utility classes. Import is `import { Name } from '<import path>'`. Props marked `?` are optional. This map is the retrieval step the [`frontend-design` skill] makes mandatory; the [CHI 2026 study] measured composing-from-a-registry at 95% design-system compliance against 71% for writing the CSS from a prose style guide.
|
|
7
7
|
|