morphico 0.2.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 +77 -3
- package/dist/morphico.js +1350 -5
- package/dist/morphico.mjs +1350 -5
- package/dist/types/clip.d.ts +57 -0
- package/dist/types/face.d.ts +31 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/morph.d.ts +5 -1
- package/dist/types/sets/faces.d.ts +25 -0
- package/dist/types/sets/shapes.d.ts +5 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Or from a CDN, as a classic script with the global `morphico`:
|
|
|
19
19
|
```html
|
|
20
20
|
<script src="https://cdn.jsdelivr.net/npm/morphico"></script>
|
|
21
21
|
<script>
|
|
22
|
-
const { icon, text } = morphico;
|
|
22
|
+
const { icon, text, clip } = morphico;
|
|
23
23
|
</script>
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -79,6 +79,80 @@ clock.destroy();
|
|
|
79
79
|
(`5` ↔ `:`). Pad counters with spaces to keep them morphing: `counter.set(String(count).padStart(3, ' '))`.
|
|
80
80
|
- Digits sit on the text baseline, and every cell has the same width, so clocks don't jiggle.
|
|
81
81
|
|
|
82
|
+
## A cut-out: `clip(element, options)`
|
|
83
|
+
|
|
84
|
+
Cuts any element (an `<img>`, a `<div>`, a `<main>` …) out by a shape, and morphs, moves, resizes and turns it.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const photo = clip(document.querySelector('#photo'), { state: 'star', x: 50, y: 50, size: '80%' });
|
|
88
|
+
|
|
89
|
+
await photo.to('heart'); // morph
|
|
90
|
+
photo.to('shield', { rotation: 360, x: 30, size: '120px' }); // morph + turn + move together
|
|
91
|
+
photo.to({ x: 70, y: '150px' }); // move only, the shape stays
|
|
92
|
+
photo.set({ rotation: 15 }); // jump, no animation (e.g. while dragging a slider)
|
|
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
|
|
95
|
+
photo.destroy(); // the element is whole again
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Shapes (based on [Lucide](https://lucide.dev)): `circle`, `ellipse`, `heart`, `sparkle`, `astroid`, `bookmark`,
|
|
99
|
+
`shield`, `moon`, `tag`, `square`, `badge`, `triangle`, `droplet`, `pentagon`, `hexagon`, `octagon`, `squircle`,
|
|
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`).
|
|
102
|
+
|
|
103
|
+
| Option | Default | |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| `state` | `'circle'` | The shape |
|
|
106
|
+
| `x`, `y` | `50` | The shape's **centre**. A number is %, or a string `'40%'` / `'120px'` (% of the element's width for `x`, height for `y`) |
|
|
107
|
+
| `size` | fits | The side of the shape's square (% of the element's width, or px). The shape keeps its own proportions inside that square. Default: the largest square that fits the element |
|
|
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 |
|
|
109
|
+
| `roundness` | `1` | Corners: `0` = sharp … `1` = the shape's own (the maximum) |
|
|
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 |
|
|
112
|
+
| `duration`, `easing` | `400`, `'easeInOutCubic'` | As for icons; also per `to()` call |
|
|
113
|
+
|
|
114
|
+
Everything except `outline` and `inverted` animates together in `to()`. How it works: a filled shape uses CSS `clip-path: url(#…)`,
|
|
115
|
+
an outlined one `mask: url(#…)` (clip-path has no line width); the `<clipPath>` / `<mask>` sit in a small hidden
|
|
116
|
+
`<svg>` that `clip()` adds to the page. It follows the element's size (`ResizeObserver`). Overflow beyond the element is
|
|
117
|
+
cut off, as with any clip-path.
|
|
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
|
+
|
|
82
156
|
## Options
|
|
83
157
|
|
|
84
158
|
| Option | For | Default | |
|
|
@@ -106,7 +180,7 @@ clock.destroy();
|
|
|
106
180
|
The earlier promise resolves with `{ interrupted: true }`; promises never stay pending.
|
|
107
181
|
- **Reduced motion:** when the user's system asks for reduced motion, shapes change without animation.
|
|
108
182
|
- **Accessibility:** the icon / line has `role="img"` and an `aria-label` with the current value.
|
|
109
|
-
- **Server-side rendering:** importing does not touch the DOM; only `icon()` / `text()` do.
|
|
183
|
+
- **Server-side rendering:** importing does not touch the DOM; only `icon()` / `text()` / `clip()` / `face()` do.
|
|
110
184
|
|
|
111
185
|
## Development
|
|
112
186
|
|
|
@@ -121,5 +195,5 @@ npm run build # src/ → dist/
|
|
|
121
195
|
|
|
122
196
|
## License
|
|
123
197
|
|
|
124
|
-
[MIT](LICENSE). The icon sets are based on [Lucide](https://lucide.dev) icons (ISC; some from Feather, MIT):
|
|
198
|
+
[MIT](LICENSE). The icon sets and clip shapes are based on [Lucide](https://lucide.dev) icons (ISC; some from Feather, MIT):
|
|
125
199
|
see [LICENSE-lucide](LICENSE-lucide).
|