@effect.healthcare/messenger 0.4.2 → 0.6.0
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/README.md +2 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/messenger.d.ts +30 -13
- package/dist/messenger.js +66 -38
- package/dist/messenger.meta.d.ts +11 -5
- package/dist/messenger.meta.js +8 -2
- package/dist/messenger.validation.d.ts +3 -3
- package/dist/messenger.validation.js +4 -7
- package/package.json +7 -2
- package/.claude/CLAUDE.md +0 -88
- package/.claude/context/composition.md +0 -921
- package/.claude/context/data.md +0 -1036
- package/.claude/context/event.md +0 -686
- package/.claude/context/gesture.md +0 -614
- package/.claude/context/operation.md +0 -596
- package/.claude/context/state.md +0 -864
- package/.claude/context/testing.md +0 -876
- package/.claude/context/validation.md +0 -350
- package/.claude/context/workflow.md +0 -608
- package/.claude/settings.json +0 -7
- package/.mcp.json +0 -12
- package/dist/.gitkeep +0 -1
- package/src/index.ts +0 -16
- package/src/messenger.meta.ts +0 -132
- package/src/messenger.ts +0 -386
- package/src/messenger.validation.ts +0 -25
- package/web-dev-server.config.mjs +0 -8
|
@@ -1,614 +0,0 @@
|
|
|
1
|
-
# Gesture
|
|
2
|
-
|
|
3
|
-
This document defines an implementation policy for **component gestures**, then illustrates how specifications are implemented by applying this policy.
|
|
4
|
-
|
|
5
|
-
This document is intentionally **gesture** only, but part of a set of implementation policies which together defines the policies which should be followed to transform specifications into an implementation which is predictable, maintainable, and production-ready at scale.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# How to Read This Policy
|
|
10
|
-
|
|
11
|
-
Rules in this policy fall into three strengths. Read each rule with its strength in mind:
|
|
12
|
-
|
|
13
|
-
- **Principles** are non-negotiable. They derive from framework correctness or TDD discipline and hold for every component. A conflict with a principle is a defect.
|
|
14
|
-
- **Templates** are invariant skeletons with explicit variation points. The skeleton applies to every component; specific steps activate or deactivate based on the component's declared classification (e.g., attribute-backed vs non-attribute, readonly vs writable, payload-bearing vs payload-free). Variation is part of the template, not a deviation from it.
|
|
15
|
-
- **Conventions** are canonical defaults that keep implementations readable across components. A second component may deviate when its shape genuinely warrants it; the deviation should be explained at review time, not forbidden by the policy.
|
|
16
|
-
|
|
17
|
-
When applying this policy to a new component, classify each rule before reconciling conflicts. A conflict with a principle is a defect; a conflict with a template means a variation point needs to be made explicit; a conflict with a convention is a documented deviation.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
# 1) Gesture Contract Must Be Declared in the Specification
|
|
22
|
-
|
|
23
|
-
Each component specification must declare its gesture contract under `Gestures`.
|
|
24
|
-
|
|
25
|
-
`Gestures` must be an object whose property names are the canonical gesture names.
|
|
26
|
-
|
|
27
|
-
Each gesture definition must include:
|
|
28
|
-
|
|
29
|
-
- `description`
|
|
30
|
-
|
|
31
|
-
A gesture definition must also declare exactly one implementation intent:
|
|
32
|
-
|
|
33
|
-
- `triggers` for behavioral gestures
|
|
34
|
-
- `effects` for visual gestures
|
|
35
|
-
|
|
36
|
-
Interpretation:
|
|
37
|
-
|
|
38
|
-
- `description` defines the user interaction intent
|
|
39
|
-
- a gesture declared with `triggers` is a behavioral gesture
|
|
40
|
-
- a gesture declared with `effects` is a visual gesture
|
|
41
|
-
- behavioral gestures describe an interaction that causes runtime behavior
|
|
42
|
-
- visual gestures describe an interaction that affects presentation only
|
|
43
|
-
- the gesture name defines the canonical gesture vocabulary used by the specification
|
|
44
|
-
- gestures declare interaction input, not semantic outcome
|
|
45
|
-
- every gesture definition must include exactly one of `triggers` or `effects`
|
|
46
|
-
|
|
47
|
-
The `effects` object declares the CSS properties affected by the visual gesture and the interaction condition. The CSS implementation is the authoritative source for per-element specifics — the spec declares the interaction intent and the set of affected properties.
|
|
48
|
-
|
|
49
|
-
Example behavioral gesture specification:
|
|
50
|
-
|
|
51
|
-
```json
|
|
52
|
-
"click": {
|
|
53
|
-
"description": "Toggle pin button when icon clicked.",
|
|
54
|
-
"triggers": {
|
|
55
|
-
"operation": "toggle",
|
|
56
|
-
"condition": "on element.icon"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Example visual gesture specification:
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
"hover": {
|
|
65
|
-
"description": "Change button appearance when hovered over the icon.",
|
|
66
|
-
"effects": {
|
|
67
|
-
"properties": ["background-color", "border-color", "box-shadow", "fill"],
|
|
68
|
-
"condition": "on element.icon"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
This defines the public interaction contract that the implementation must honor.
|
|
74
|
-
|
|
75
|
-
# 2) Gestures Must Represent Interaction Inputs
|
|
76
|
-
|
|
77
|
-
This framework distinguishes:
|
|
78
|
-
|
|
79
|
-
- `Gestures`: the set of user or runtime interactions recognized by the component
|
|
80
|
-
- `Operations`: the set of callable public actions exposed by the component
|
|
81
|
-
- `Events`: the set of observable semantic outcomes exposed by the component
|
|
82
|
-
- `State`: the set of component-owned values that may be read, mutated, or reflected
|
|
83
|
-
|
|
84
|
-
Policy:
|
|
85
|
-
|
|
86
|
-
- gestures describe interaction input
|
|
87
|
-
- operations describe callable public action
|
|
88
|
-
- events describe semantic outcome
|
|
89
|
-
- state describes component-owned value
|
|
90
|
-
- gestures must not be used to declare operations
|
|
91
|
-
- gestures must not be used to declare events
|
|
92
|
-
- gestures must not be used to declare state
|
|
93
|
-
|
|
94
|
-
Examples of valid gestures:
|
|
95
|
-
|
|
96
|
-
- `click`
|
|
97
|
-
- `hover`
|
|
98
|
-
- `focus`
|
|
99
|
-
- `keydown`
|
|
100
|
-
|
|
101
|
-
Examples that must not be modeled as gestures:
|
|
102
|
-
|
|
103
|
-
- `toggle`
|
|
104
|
-
- `pin`
|
|
105
|
-
- `onpin`
|
|
106
|
-
- `visibility`
|
|
107
|
-
- `status`
|
|
108
|
-
|
|
109
|
-
A component may support both behavioral and visual interaction responses, but each declared gesture remains a single interaction input with a single declared implementation role.
|
|
110
|
-
|
|
111
|
-
# 3) Gestures Must Be Classified by Implementation Role
|
|
112
|
-
|
|
113
|
-
Every declared gesture must be classified as exactly one of:
|
|
114
|
-
|
|
115
|
-
- **Behavioral**
|
|
116
|
-
- **Visual**
|
|
117
|
-
|
|
118
|
-
This classification determines whether the gesture participates in runtime implementation or presentation-only implementation.
|
|
119
|
-
|
|
120
|
-
## 3.1) Behavioral Gestures
|
|
121
|
-
|
|
122
|
-
Behavioral gestures are interaction inputs that trigger runtime behavior.
|
|
123
|
-
|
|
124
|
-
A behavioral gesture may:
|
|
125
|
-
|
|
126
|
-
- invoke a declared public operation
|
|
127
|
-
- delegate through an authoritative mutation path when no public operation exists for the behavior
|
|
128
|
-
- indirectly produce accepted state transitions
|
|
129
|
-
- indirectly cause semantic event emission
|
|
130
|
-
|
|
131
|
-
Examples:
|
|
132
|
-
|
|
133
|
-
- `click`
|
|
134
|
-
- `keydown`
|
|
135
|
-
- `drag`
|
|
136
|
-
|
|
137
|
-
## 3.2) Visual Gestures
|
|
138
|
-
|
|
139
|
-
Visual gestures are interaction inputs that affect presentation only.
|
|
140
|
-
|
|
141
|
-
A visual gesture may:
|
|
142
|
-
|
|
143
|
-
- change appearance through CSS
|
|
144
|
-
- express interaction feedback such as hover, focus, or active styling
|
|
145
|
-
|
|
146
|
-
A visual gesture must not by itself:
|
|
147
|
-
|
|
148
|
-
- invoke operations
|
|
149
|
-
- mutate component state
|
|
150
|
-
- dispatch component events
|
|
151
|
-
|
|
152
|
-
Examples:
|
|
153
|
-
|
|
154
|
-
- `hover`
|
|
155
|
-
- `focus` styling
|
|
156
|
-
- `active` styling
|
|
157
|
-
|
|
158
|
-
## 3.3) Classification Must Match the Specification Contract
|
|
159
|
-
|
|
160
|
-
Interpretation:
|
|
161
|
-
|
|
162
|
-
- a gesture declared with `triggers` is behavioral
|
|
163
|
-
- a gesture declared with `effects` is visual
|
|
164
|
-
- the implementation strategy must follow that declared classification
|
|
165
|
-
- a gesture must not be implemented partly as behavioral and partly as visual unless the specification declares separate gestures for those distinct concerns
|
|
166
|
-
|
|
167
|
-
# 4) Runtime Gesture Names Must Be Declared in Metadata
|
|
168
|
-
|
|
169
|
-
For every behavioral gesture declared in the specification, the implementation must define corresponding metadata in `<component>.meta.ts`.
|
|
170
|
-
|
|
171
|
-
`Gesture` metadata represents the canonical runtime gesture vocabulary, not the full declared gesture vocabulary from the specification.
|
|
172
|
-
|
|
173
|
-
Policy:
|
|
174
|
-
|
|
175
|
-
- every declared behavioral gesture must have a key in `Gesture`
|
|
176
|
-
- `Gesture` contains only behavioral gestures that participate in runtime listener wiring
|
|
177
|
-
- visual gestures must not be declared in `Gesture` when they are implemented purely through CSS
|
|
178
|
-
- the implementation must use gesture metadata consistently as the canonical runtime gesture vocabulary
|
|
179
|
-
|
|
180
|
-
Example pattern:
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
export const Gesture = {
|
|
184
|
-
CLICK: "click",
|
|
185
|
-
} as const;
|
|
186
|
-
|
|
187
|
-
export type Gesture = (typeof Gesture)[keyof typeof Gesture];
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
This gives the implementation a stable, centralized gesture vocabulary that prevents string duplication and keeps listener wiring consistent across metadata and component runtime implementation.
|
|
191
|
-
|
|
192
|
-
# 5) Runtime Gesture Listener Lifecycle Must Be Centralized
|
|
193
|
-
|
|
194
|
-
Behavioral gestures must be wired through a centralized listener lifecycle on the component class.
|
|
195
|
-
|
|
196
|
-
Required methods:
|
|
197
|
-
|
|
198
|
-
- `_addEventListeners`
|
|
199
|
-
- `_removeEventListeners`
|
|
200
|
-
|
|
201
|
-
These methods define the authoritative attachment and detachment points for runtime gesture listeners.
|
|
202
|
-
|
|
203
|
-
Policy:
|
|
204
|
-
|
|
205
|
-
- behavioral gesture listeners must be attached in `_addEventListeners`
|
|
206
|
-
- behavioral gesture listeners must be removed in `_removeEventListeners`
|
|
207
|
-
- listener lifecycle must be reversible
|
|
208
|
-
- listener wiring must not be scattered across unrelated lifecycle or helper methods
|
|
209
|
-
- visual gestures implemented only through CSS must not participate in this runtime listener lifecycle
|
|
210
|
-
|
|
211
|
-
Example:
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
protected _addEventListeners = () =>
|
|
215
|
-
this.elements.icon?.addEventListener(Gesture.CLICK, this._handleClick);
|
|
216
|
-
|
|
217
|
-
protected _removeEventListeners = () =>
|
|
218
|
-
this.elements.icon?.removeEventListener(Gesture.CLICK, this._handleClick);
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
# 6) Runtime Gesture Listeners Must Target Explicit DOM References
|
|
222
|
-
|
|
223
|
-
Behavioral gesture listeners must be attached to explicit component-owned DOM references.
|
|
224
|
-
|
|
225
|
-
These references should be cached on the component instance and used as the authoritative listener targets.
|
|
226
|
-
|
|
227
|
-
Policy:
|
|
228
|
-
|
|
229
|
-
- runtime gesture listeners must target explicit DOM references owned by the component
|
|
230
|
-
- listener targets should be obtained during the component's caching phase
|
|
231
|
-
- runtime listener wiring must use cached references rather than repeated selector queries
|
|
232
|
-
- listener wiring must not depend on ad hoc selector lookup at the point of attachment
|
|
233
|
-
- the specification target described by the gesture contract must be traceable to the implementation target reference
|
|
234
|
-
|
|
235
|
-
Example:
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
protected elements: { icon: HTMLDivElement | null } = { icon: null };
|
|
239
|
-
|
|
240
|
-
protected _cache = () => {
|
|
241
|
-
this.elements.icon = this.root.querySelector(".icon");
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
protected _addEventListeners = () =>
|
|
245
|
-
this.elements.icon?.addEventListener(Gesture.CLICK, this._handleClick);
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
This keeps gesture wiring stable, explicit, and resilient to template complexity while preserving a predictable mapping from specification target to implementation target.
|
|
249
|
-
|
|
250
|
-
# 7) Runtime Gestures Must Route Through Dedicated Handlers
|
|
251
|
-
|
|
252
|
-
Each behavioral gesture listener must delegate to a dedicated handler method on the component class.
|
|
253
|
-
|
|
254
|
-
The handler defines the component's immediate response entry for that gesture.
|
|
255
|
-
|
|
256
|
-
Policy:
|
|
257
|
-
|
|
258
|
-
- every behavioral gesture listener must call a dedicated handler
|
|
259
|
-
- the handler must be a component method with a name that predictably reflects the gesture, such as `_handleClick`
|
|
260
|
-
- handler methods must remain small and focused on gesture routing intent
|
|
261
|
-
- listener wiring must not inline gesture behavior directly inside `_addEventListeners`
|
|
262
|
-
- visual gestures implemented only through CSS do not require handler methods
|
|
263
|
-
|
|
264
|
-
Example:
|
|
265
|
-
|
|
266
|
-
```typescript
|
|
267
|
-
protected _addEventListeners = () =>
|
|
268
|
-
this.elements.icon?.addEventListener(Gesture.CLICK, this._handleClick);
|
|
269
|
-
|
|
270
|
-
private _handleClick = () => this.toggle();
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
This keeps listener wiring declarative, preserves readable separation between attachment and behavior routing, and gives each behavioral gesture a clear implementation entry point.
|
|
274
|
-
|
|
275
|
-
# 8) Behavioral Gestures Must Route Through the Canonical Behavior Entry
|
|
276
|
-
|
|
277
|
-
When a behavioral gesture triggers behavior that is declared as a public operation, the gesture handler must invoke that operation.
|
|
278
|
-
|
|
279
|
-
If the behavior is not declared as a public operation, the gesture handler must delegate through the authoritative mutation path of the relevant construct.
|
|
280
|
-
|
|
281
|
-
Policy:
|
|
282
|
-
|
|
283
|
-
- if a behavior is declared in `Operations`, behavioral gesture handlers must invoke that operation
|
|
284
|
-
- gesture handlers must not reimplement declared public action logic inline
|
|
285
|
-
- if no public operation exists for the behavior, the handler must use the authoritative mutation path of the affected construct
|
|
286
|
-
- gesture handlers remain the interaction entry point, not the authoritative owner of mutation logic, transition acceptance, or semantic event emission
|
|
287
|
-
|
|
288
|
-
Example:
|
|
289
|
-
|
|
290
|
-
```typescript
|
|
291
|
-
private _handleClick = () => this.toggle();
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
Preferred flow when the behavior is declared as an operation:
|
|
295
|
-
|
|
296
|
-
```text
|
|
297
|
-
gesture
|
|
298
|
-
↓
|
|
299
|
-
handler
|
|
300
|
-
↓
|
|
301
|
-
operation
|
|
302
|
-
↓
|
|
303
|
-
construct mutation
|
|
304
|
-
↓
|
|
305
|
-
accepted outcome
|
|
306
|
-
↓
|
|
307
|
-
event dispatch
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
In this example, the click handler does not implement toggle behavior itself. It delegates to `toggle()`, keeping the operation layer as the single reusable action entry for both runtime interaction and imperative use.
|
|
311
|
-
|
|
312
|
-
# 9) Visual Gestures Should Prefer CSS
|
|
313
|
-
|
|
314
|
-
When a declared visual gesture affects presentation only, the implementation should realize that gesture directly in CSS.
|
|
315
|
-
|
|
316
|
-
These gestures do not participate in runtime listener wiring.
|
|
317
|
-
|
|
318
|
-
Policy:
|
|
319
|
-
|
|
320
|
-
- visual gestures that affect presentation only should be implemented in CSS
|
|
321
|
-
- CSS-implemented visual gestures must not require entries in runtime gesture metadata
|
|
322
|
-
- CSS-implemented visual gestures must not require `_addEventListeners` or `_removeEventListeners`
|
|
323
|
-
- CSS-implemented visual gestures must not require dedicated runtime handler methods
|
|
324
|
-
- visual gesture implementation should remain traceable to the declared specification target and effect
|
|
325
|
-
|
|
326
|
-
Example specification:
|
|
327
|
-
|
|
328
|
-
```json
|
|
329
|
-
"hover": {
|
|
330
|
-
"description": "Change button appearance when hovered over the icon.",
|
|
331
|
-
"effects": {
|
|
332
|
-
"properties": ["background-color", "border-color", "box-shadow", "fill"],
|
|
333
|
-
"condition": "on element.icon"
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Example implementation:
|
|
339
|
-
|
|
340
|
-
```css
|
|
341
|
-
@media (hover: hover) {
|
|
342
|
-
.icon:hover {
|
|
343
|
-
background-color: var(--button-hover-background-color);
|
|
344
|
-
border-color: var(--button-border-hover-color);
|
|
345
|
-
box-shadow: var(--button-shadow-hover);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
.icon:hover svg {
|
|
349
|
-
fill: var(--svg-hover-fill-color);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
This keeps presentation-only interaction in the presentation layer and avoids promoting visual feedback into unnecessary runtime behavior.
|
|
355
|
-
|
|
356
|
-
# 10) CSS-Implemented Visual Gestures Must Not Become Runtime Behavior
|
|
357
|
-
|
|
358
|
-
A visual gesture implemented in CSS must remain presentation-only.
|
|
359
|
-
|
|
360
|
-
It must not become an implicit behavioral gesture unless the specification declares a behavioral contract for that interaction.
|
|
361
|
-
|
|
362
|
-
Policy:
|
|
363
|
-
|
|
364
|
-
- a CSS-implemented visual gesture must not invoke operations
|
|
365
|
-
- a CSS-implemented visual gesture must not mutate component state
|
|
366
|
-
- a CSS-implemented visual gesture must not dispatch component events
|
|
367
|
-
- if an interaction requires runtime behavior, that behavior must be declared and implemented as a behavioral gesture
|
|
368
|
-
- visual feedback and behavioral response must remain separately modeled unless the specification explicitly declares both concerns
|
|
369
|
-
|
|
370
|
-
Example:
|
|
371
|
-
|
|
372
|
-
```css
|
|
373
|
-
@media (hover: hover) {
|
|
374
|
-
.icon:hover {
|
|
375
|
-
background-color: var(--button-hover-background-color);
|
|
376
|
-
border-color: var(--button-border-hover-color);
|
|
377
|
-
box-shadow: var(--button-shadow-hover);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
.icon:hover svg {
|
|
381
|
-
fill: var(--svg-hover-fill-color);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
In this example, `hover` changes appearance only. It does not call `toggle()`, change `status`, or emit `onpin`.
|
|
387
|
-
|
|
388
|
-
# Policy Applied to Specification
|
|
389
|
-
|
|
390
|
-
Specification fragment:
|
|
391
|
-
|
|
392
|
-
```json
|
|
393
|
-
{
|
|
394
|
-
"Gestures": {
|
|
395
|
-
"click": {
|
|
396
|
-
"description": "User clicks the icon to toggle the pin status.",
|
|
397
|
-
"triggers": {
|
|
398
|
-
"operation": "toggle",
|
|
399
|
-
"condition": "on element.icon"
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
"hover": {
|
|
403
|
-
"description": "Changes the button appearance when hovered.",
|
|
404
|
-
"effects": {
|
|
405
|
-
"properties": ["background-color", "border-color", "box-shadow", "fill"],
|
|
406
|
-
"condition": "on element.icon"
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
How this specification is implemented:
|
|
414
|
-
|
|
415
|
-
- `click`
|
|
416
|
-
- behavioral gesture
|
|
417
|
-
- declared in runtime gesture metadata as `Gesture.CLICK`
|
|
418
|
-
- wired through the runtime listener lifecycle in `_addEventListeners` and `_removeEventListeners`
|
|
419
|
-
- attached to the cached DOM reference `elements.icon`
|
|
420
|
-
- routed through the dedicated handler `_handleClick`
|
|
421
|
-
- delegated to the declared public operation `toggle()`
|
|
422
|
-
- `hover`
|
|
423
|
-
- visual gesture
|
|
424
|
-
- not declared in runtime gesture metadata — implemented purely through CSS
|
|
425
|
-
- not wired through runtime listener lifecycle
|
|
426
|
-
- realized in CSS on the `.icon` and `.icon svg` targets using the declared presentation effects
|
|
427
|
-
- the `effects.properties` array declares the full set of affected CSS properties; per-element specifics are an implementation detail expressed in CSS
|
|
428
|
-
|
|
429
|
-
Implementation:
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
export const Gesture = {
|
|
433
|
-
CLICK: "click",
|
|
434
|
-
} as const;
|
|
435
|
-
|
|
436
|
-
protected _addEventListeners = () =>
|
|
437
|
-
this.elements.icon?.addEventListener(Gesture.CLICK, this._handleClick);
|
|
438
|
-
|
|
439
|
-
protected _removeEventListeners = () =>
|
|
440
|
-
this.elements.icon?.removeEventListener(Gesture.CLICK, this._handleClick);
|
|
441
|
-
|
|
442
|
-
private _handleClick = () => this.toggle();
|
|
443
|
-
```
|
|
444
|
-
|
|
445
|
-
```css
|
|
446
|
-
@media (hover: hover) {
|
|
447
|
-
.icon:hover {
|
|
448
|
-
background-color: var(--button-hover-background-color);
|
|
449
|
-
border-color: var(--button-border-hover-color);
|
|
450
|
-
box-shadow: var(--button-shadow-hover);
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
.icon:hover svg {
|
|
454
|
-
fill: var(--svg-hover-fill-color);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
How the implementation applies the policy:
|
|
460
|
-
|
|
461
|
-
- the specification declares the interaction contract under `Gestures`
|
|
462
|
-
- behavioral and visual gestures are classified by specification shape (`triggers` vs `effects`)
|
|
463
|
-
- behavioral gestures become part of the canonical runtime `Gesture` vocabulary
|
|
464
|
-
- behavioral gesture listeners are attached and removed through the centralized listener lifecycle
|
|
465
|
-
- behavioral listeners target explicit cached DOM references
|
|
466
|
-
- behavioral listeners route through dedicated handlers
|
|
467
|
-
- handlers delegate to the canonical behavior entry — the declared public operation when one exists
|
|
468
|
-
- visual gestures that affect presentation only are implemented in CSS
|
|
469
|
-
- the `effects` spec declares the full set of affected CSS properties; per-element specifics are implementation detail owned by CSS
|
|
470
|
-
- CSS-implemented visual gestures do not participate in runtime metadata, listener wiring, handler methods, state mutation, or event dispatch
|
|
471
|
-
|
|
472
|
-
# Policy Checklist
|
|
473
|
-
|
|
474
|
-
A compliant component must:
|
|
475
|
-
|
|
476
|
-
1. Declare all gestures under `Gestures` in the specification.
|
|
477
|
-
2. Define each gesture using the required specification contract.
|
|
478
|
-
3. Classify every declared gesture as either behavioral (`triggers`) or visual (`effects`).
|
|
479
|
-
4. Ensure every gesture definition includes exactly one of `triggers` or `effects`.
|
|
480
|
-
5. Ensure the gesture classification matches the declared specification shape.
|
|
481
|
-
6. Define every declared behavioral gesture in `<component>.meta.ts` as part of the canonical runtime `Gesture` vocabulary.
|
|
482
|
-
7. Avoid declaring CSS-only visual gestures in runtime gesture metadata.
|
|
483
|
-
8. Attach behavioral gesture listeners in `_addEventListeners`.
|
|
484
|
-
9. Remove behavioral gesture listeners in `_removeEventListeners`.
|
|
485
|
-
10. Keep runtime gesture listener lifecycle centralized and reversible.
|
|
486
|
-
11. Target explicit component-owned DOM references for behavioral gesture listeners.
|
|
487
|
-
12. Obtain listener targets through the component caching path and reuse cached references during wiring.
|
|
488
|
-
13. Route every behavioral gesture through a dedicated handler method.
|
|
489
|
-
14. Keep dedicated handler methods small and focused on gesture routing intent.
|
|
490
|
-
15. Invoke the declared public operation when the behavioral gesture maps to behavior declared in `Operations`.
|
|
491
|
-
16. Avoid reimplementing declared public action logic inline in gesture handlers.
|
|
492
|
-
17. When no public operation exists for the behavior, delegate through the authoritative mutation path of the affected construct.
|
|
493
|
-
18. Implement presentation-only visual gestures in CSS.
|
|
494
|
-
19. Keep CSS-implemented visual gestures out of runtime listener wiring.
|
|
495
|
-
20. Ensure CSS-implemented visual gestures do not invoke operations, mutate component state, or dispatch component events.
|
|
496
|
-
21. List all affected CSS properties in `effects.properties` — per-element specifics are implementation detail owned by the CSS file.
|
|
497
|
-
22. Keep gesture naming and implementation traceable from specification target to implementation target and behavior path.
|
|
498
|
-
|
|
499
|
-
---
|
|
500
|
-
|
|
501
|
-
# Component Gesture Specification Schema
|
|
502
|
-
|
|
503
|
-
JSON Schema:
|
|
504
|
-
|
|
505
|
-
```json
|
|
506
|
-
{
|
|
507
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
508
|
-
"$id": "https://scalable.software/schema/component-gestures.schema.json",
|
|
509
|
-
"title": "Component Gestures",
|
|
510
|
-
"description": "Schema for the Gestures object in a component specification.",
|
|
511
|
-
"type": "object",
|
|
512
|
-
"propertyNames": {
|
|
513
|
-
"type": "string",
|
|
514
|
-
"pattern": "^[a-z][a-zA-Z0-9]*$",
|
|
515
|
-
"description": "Canonical gesture name in lowerCamelCase, for example: click, hover, focus, keydown."
|
|
516
|
-
},
|
|
517
|
-
"additionalProperties": {
|
|
518
|
-
"type": "object",
|
|
519
|
-
"description": "A gesture definition.",
|
|
520
|
-
"required": ["description"],
|
|
521
|
-
"additionalProperties": false,
|
|
522
|
-
"properties": {
|
|
523
|
-
"description": {
|
|
524
|
-
"type": "string",
|
|
525
|
-
"minLength": 1,
|
|
526
|
-
"description": "Human-readable description of the interaction input represented by the gesture."
|
|
527
|
-
},
|
|
528
|
-
"triggers": {
|
|
529
|
-
"type": "object",
|
|
530
|
-
"description": "Behavioral gesture contract. Presence of this object means the gesture triggers runtime behavior.",
|
|
531
|
-
"required": ["condition"],
|
|
532
|
-
"minProperties": 1,
|
|
533
|
-
"additionalProperties": false,
|
|
534
|
-
"properties": {
|
|
535
|
-
"operation": {
|
|
536
|
-
"type": "string",
|
|
537
|
-
"pattern": "^[a-z][a-zA-Z0-9]*$",
|
|
538
|
-
"description": "Canonical operation name triggered by this gesture, for example: toggle, pin, hide."
|
|
539
|
-
},
|
|
540
|
-
"condition": {
|
|
541
|
-
"type": "string",
|
|
542
|
-
"minLength": 1,
|
|
543
|
-
"description": "Human-readable interaction target and condition, for example: on element.icon."
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
},
|
|
547
|
-
"effects": {
|
|
548
|
-
"type": "object",
|
|
549
|
-
"description": "Visual gesture contract. Presence of this object means the gesture affects presentation only. The properties array declares the full set of affected CSS properties across all targeted elements — per-element specifics are implementation detail owned by the CSS file.",
|
|
550
|
-
"required": ["properties", "condition"],
|
|
551
|
-
"additionalProperties": false,
|
|
552
|
-
"properties": {
|
|
553
|
-
"properties": {
|
|
554
|
-
"type": "array",
|
|
555
|
-
"description": "All CSS properties affected by the gesture across all targeted elements, for example: background-color, border-color, box-shadow, fill.",
|
|
556
|
-
"minItems": 1,
|
|
557
|
-
"items": {
|
|
558
|
-
"type": "string",
|
|
559
|
-
"minLength": 1
|
|
560
|
-
}
|
|
561
|
-
},
|
|
562
|
-
"condition": {
|
|
563
|
-
"type": "string",
|
|
564
|
-
"minLength": 1,
|
|
565
|
-
"description": "Human-readable interaction target and condition, for example: on element.icon."
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
},
|
|
570
|
-
"oneOf": [
|
|
571
|
-
{
|
|
572
|
-
"required": ["triggers"],
|
|
573
|
-
"not": {
|
|
574
|
-
"required": ["effects"]
|
|
575
|
-
}
|
|
576
|
-
},
|
|
577
|
-
{
|
|
578
|
-
"required": ["effects"],
|
|
579
|
-
"not": {
|
|
580
|
-
"required": ["triggers"]
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
]
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
Example JSON:
|
|
589
|
-
|
|
590
|
-
```json
|
|
591
|
-
{
|
|
592
|
-
"Gestures": {
|
|
593
|
-
"click": {
|
|
594
|
-
"description": "User clicks the icon to toggle the pin status.",
|
|
595
|
-
"triggers": {
|
|
596
|
-
"operation": "toggle",
|
|
597
|
-
"condition": "on element.icon"
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
|
-
"hover": {
|
|
601
|
-
"description": "Changes the button appearance when hovered.",
|
|
602
|
-
"effects": {
|
|
603
|
-
"properties": [
|
|
604
|
-
"background-color",
|
|
605
|
-
"border-color",
|
|
606
|
-
"box-shadow",
|
|
607
|
-
"fill"
|
|
608
|
-
],
|
|
609
|
-
"condition": "on element.icon"
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
```
|