@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.
@@ -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
- ```