morphico 0.3.0 → 0.4.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 CHANGED
@@ -91,12 +91,14 @@ photo.to('shield', { rotation: 360, x: 30, size: '120px' }); // morph + turn + m
91
91
  photo.to({ x: 70, y: '150px' }); // move only, the shape stays
92
92
  photo.set({ rotation: 15 }); // jump, no animation (e.g. while dragging a slider)
93
93
  photo.set({ outline: { width: 16 } }); // only a 16 px band along the edge shows
94
+ photo.set({ inverted: true }); // the other way round: the shape is a hole
94
95
  photo.destroy(); // the element is whole again
95
96
  ```
96
97
 
97
98
  Shapes (based on [Lucide](https://lucide.dev)): `circle`, `ellipse`, `heart`, `sparkle`, `astroid`, `bookmark`,
98
99
  `shield`, `moon`, `tag`, `square`, `badge`, `triangle`, `droplet`, `pentagon`, `hexagon`, `octagon`, `squircle`,
99
- `star`, `rectangle-horizontal`, `rectangle-vertical`, `message-circle`, `message-square`, `diamond`, `cloud`, `puzzle`.
100
+ `star`, `rectangle-horizontal`, `message-circle`, `message-square`, `cloud`, `puzzle`, `club`. A diamond is the `square`
101
+ turned 45°, a portrait rectangle `rectangle-horizontal` turned 90° (`rotation`).
100
102
 
101
103
  | Option | Default | |
102
104
  | --- | --- | --- |
@@ -106,13 +108,51 @@ Shapes (based on [Lucide](https://lucide.dev)): `circle`, `ellipse`, `heart`, `s
106
108
  | `rotation` | `0` | Degrees, clockwise, **absolute**: `rotation: 360` ends one full turn from 0. The shape turns rigidly, also in a wide or tall element |
107
109
  | `roundness` | `1` | Corners: `0` = sharp … `1` = the shape's own (the maximum) |
108
110
  | `outline` | `false` | `{ width, band }`: only a band of `width` px along the edge shows; `band`: `'inside'` (default), `'centre'` or `'outside'` the edge. Not animated |
111
+ | `inverted` | `false` | `true`: the other way round — the shape (or band) is a hole, the rest of the element shows. Not animated |
109
112
  | `duration`, `easing` | `400`, `'easeInOutCubic'` | As for icons; also per `to()` call |
110
113
 
111
- Everything except `outline` animates together in `to()`. How it works: a filled shape uses CSS `clip-path: url(#…)`,
114
+ Everything except `outline` and `inverted` animates together in `to()`. How it works: a filled shape uses CSS `clip-path: url(#…)`,
112
115
  an outlined one `mask: url(#…)` (clip-path has no line width); the `<clipPath>` / `<mask>` sit in a small hidden
113
116
  `<svg>` that `clip()` adds to the page. It follows the element's size (`ResizeObserver`). Overflow beyond the element is
114
117
  cut off, as with any clip-path.
115
118
 
119
+ ## A face: `face(element, options)`
120
+
121
+ A face of 7 soft pieces — 2 brows, 2 eyes, 2 pupils and a mouth — that morphs between feelings and blinks.
122
+
123
+ ```html
124
+ <div id="robot" style="width: 160px; height: 160px; border-radius: 50%; background: #e4e2d6; color: #8b8e8e"></div>
125
+ ```
126
+
127
+ ```ts
128
+ import { face } from 'morphico';
129
+
130
+ const robot = face(document.querySelector('#robot'), { state: 'normal' });
131
+
132
+ await robot.to('smiling'); // morph
133
+ robot.to('angry', { duration: 300, onEnd: (result) => console.log(result) });
134
+ robot.blink(); // close and open the eyes once, on top of any expression
135
+ robot.state; // 'angry'
136
+ robot.destroy(); // removes the face, stops blinking
137
+ ```
138
+
139
+ Expressions: `normal`, `smiling`, `pleading`, `wonder`, `focused`, `fright`, `angry`, `asleep`, `sad`,
140
+ `surprised`, `laughing`, `tired`, `wink-left`, `wink-right`, `suspicious`, `confused`, `smug`, `irritated`,
141
+ `bored`, `curious`, `empathetic`, `guilty`, `worried`, `disappointed`, `ashamed`, `embarrassed`, `yearning`,
142
+ `triumphant`, `proud`, `excited`, `scornful`, `disgusted` (also exported as `faceExpressionNames`). Any one
143
+ morphs into any other. `wink-left` / `wink-right` = the eye that closes, as seen.
144
+
145
+ | Option | Default | |
146
+ | --- | --- | --- |
147
+ | `state` | `'normal'` | The expression shown first |
148
+ | `pupilColor` | `'white'` | Colour of the pupils. Brows, eyes and mouth take the CSS `color` |
149
+ | `blink` | `true` | Blink by itself every few seconds |
150
+ | `size` | `'100%'` | CSS width and height of the face (by default it fills the element) |
151
+ | `duration`, `easing` | `500`, `'easeInOutCubic'` | As for icons; also per `to()` call |
152
+
153
+ The face draws no background: a disc, card or anything else behind it is the element's own CSS. The pupils only show
154
+ inside the eyes (an eyelid covers them). With reduced motion the face changes without animation and doesn't blink.
155
+
116
156
  ## Options
117
157
 
118
158
  | Option | For | Default | |
@@ -140,7 +180,7 @@ cut off, as with any clip-path.
140
180
  The earlier promise resolves with `{ interrupted: true }`; promises never stay pending.
141
181
  - **Reduced motion:** when the user's system asks for reduced motion, shapes change without animation.
142
182
  - **Accessibility:** the icon / line has `role="img"` and an `aria-label` with the current value.
143
- - **Server-side rendering:** importing does not touch the DOM; only `icon()` / `text()` / `clip()` do.
183
+ - **Server-side rendering:** importing does not touch the DOM; only `icon()` / `text()` / `clip()` / `face()` do.
144
184
 
145
185
  ## Development
146
186