slot-text 0.2.2 → 0.3.2
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 +124 -141
- package/dist/index.js +1 -1
- package/dist/solid.d.ts +14 -0
- package/dist/solid.js +22 -0
- package/dist/svelte.d.ts +9 -0
- package/dist/svelte.js +16 -0
- package/examples/env.d.ts +1 -0
- package/examples/solid.tsx +30 -0
- package/examples/svelte.svelte +27 -0
- package/examples/tsconfig.json +18 -0
- package/package.json +29 -3
- package/style.css +2 -1
- package/style.css.d.ts +2 -0
package/README.md
CHANGED
|
@@ -1,208 +1,191 @@
|
|
|
1
1
|
# slot-text
|
|
2
2
|
|
|
3
|
+
<p>
|
|
4
|
+
<a href="https://www.npmjs.com/package/slot-text"><img src="https://img.shields.io/npm/v/slot-text?color=cb3837&label=npm" alt="npm version"></a>
|
|
5
|
+
<img src="https://img.shields.io/badge/dependencies-zero-22c55e" alt="zero dependencies">
|
|
6
|
+
<img src="https://img.shields.io/bundlephobia/minzip/slot-text?color=8b5cf6&label=size" alt="bundle size">
|
|
7
|
+
<img src="https://img.shields.io/badge/react-✓-61dafb" alt="react">
|
|
8
|
+
<img src="https://img.shields.io/badge/vue-✓-42b883" alt="vue">
|
|
9
|
+
<img src="https://img.shields.io/badge/solid-✓-2c4f7c" alt="solid">
|
|
10
|
+
<img src="https://img.shields.io/badge/svelte-✓-ff3e00" alt="svelte">
|
|
11
|
+
<img src="https://img.shields.io/badge/typescript-✓-3178c6" alt="typescript">
|
|
12
|
+
</p>
|
|
13
|
+
|
|
3
14
|
Dependency-free text roll animation for tiny, tactile UI labels.
|
|
4
15
|
|
|
5
|
-
|
|
16
|
+
## 📦 Install
|
|
17
|
+
|
|
18
|
+
Choose your preferred package manager:
|
|
6
19
|
|
|
7
|
-
|
|
20
|
+
**npm**
|
|
8
21
|
|
|
9
22
|
```bash
|
|
10
23
|
npm install slot-text
|
|
11
24
|
```
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
**pnpm**
|
|
14
27
|
|
|
15
|
-
|
|
28
|
+
```bash
|
|
29
|
+
pnpm add slot-text
|
|
30
|
+
```
|
|
16
31
|
|
|
17
|
-
|
|
18
|
-
import "slot-text/style.css";
|
|
19
|
-
import { slotText, chromatic } from "slot-text";
|
|
32
|
+
**Bun**
|
|
20
33
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
label.set("Copied", {
|
|
24
|
-
direction: "up",
|
|
25
|
-
color: chromatic(),
|
|
26
|
-
});
|
|
34
|
+
```bash
|
|
35
|
+
bun add slot-text
|
|
27
36
|
```
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
**Yarn**
|
|
30
39
|
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
import { SlotText } from "slot-text/react";
|
|
34
|
-
import { chromatic } from "slot-text";
|
|
35
|
-
|
|
36
|
-
export function CopyLabel({ copied }: { copied: boolean }) {
|
|
37
|
-
return (
|
|
38
|
-
<SlotText
|
|
39
|
-
text={copied ? "Copied" : "Copy"}
|
|
40
|
-
options={{
|
|
41
|
-
direction: copied ? "up" : "down",
|
|
42
|
-
skipUnchanged: false,
|
|
43
|
-
color: copied ? chromatic() : undefined,
|
|
44
|
-
}}
|
|
45
|
-
/>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
40
|
+
```bash
|
|
41
|
+
yarn add slot-text
|
|
48
42
|
```
|
|
49
43
|
|
|
50
|
-
|
|
44
|
+
## 🚀 Quick start
|
|
51
45
|
|
|
52
|
-
```
|
|
53
|
-
<script setup lang="ts">
|
|
46
|
+
```ts
|
|
54
47
|
import "slot-text/style.css";
|
|
55
|
-
import {
|
|
56
|
-
import { chromatic } from "slot-text";
|
|
48
|
+
import { slotText, chromatic } from "slot-text";
|
|
57
49
|
|
|
58
|
-
const
|
|
59
|
-
direction: "up",
|
|
60
|
-
skipUnchanged: false,
|
|
61
|
-
color: chromatic(),
|
|
62
|
-
} as const;
|
|
63
|
-
</script>
|
|
50
|
+
const label = slotText(document.querySelector("#copy")!, "Copy");
|
|
64
51
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
</template>
|
|
52
|
+
// the classic Copy → Copied → Copy, in one call
|
|
53
|
+
label.flash("Copied", { enter: { color: chromatic() } });
|
|
68
54
|
```
|
|
69
55
|
|
|
70
|
-
|
|
56
|
+
That's it — import the CSS once, attach to an element, roll text.
|
|
57
|
+
|
|
58
|
+
## 🧩 API
|
|
71
59
|
|
|
72
|
-
|
|
60
|
+
| Method | What it does |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `set(text, options?)` | Roll to new text — the text **stays** |
|
|
63
|
+
| `flash(text, options?)` | Roll in, then **auto-revert** to the previous text |
|
|
64
|
+
| `destroy()` | Clean up |
|
|
73
65
|
|
|
74
66
|
```ts
|
|
75
67
|
const label = slotText(element, "Copy", options);
|
|
76
68
|
|
|
77
|
-
label.set("Copied");
|
|
69
|
+
label.set("Copied"); // permanent change
|
|
78
70
|
label.set("Copy", { direction: "down" });
|
|
79
|
-
label.flash("Copied");
|
|
71
|
+
label.flash("Copied"); // temporary — rolls back after 1.4s
|
|
80
72
|
label.destroy();
|
|
81
73
|
```
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
flashes restart the revert timer instead of queuing extra rolls, and an
|
|
86
|
-
explicit `set()` cancels any pending revert.
|
|
75
|
+
> 💡 **`flash` is spam-safe** — repeat clicks restart the revert timer instead
|
|
76
|
+
> of queuing extra rolls, and an explicit `set()` cancels any pending revert.
|
|
87
77
|
|
|
88
78
|
```ts
|
|
89
79
|
label.flash("Copied", {
|
|
90
|
-
revertAfter: 1400,
|
|
91
|
-
enter: { direction: "up", color: chromatic() }, // roll-in
|
|
92
|
-
exit: { direction: "down" },
|
|
80
|
+
revertAfter: 1400, // ms before rolling back
|
|
81
|
+
enter: { direction: "up", color: chromatic() }, // roll-in
|
|
82
|
+
exit: { direction: "down" }, // roll-back
|
|
93
83
|
});
|
|
94
84
|
```
|
|
95
85
|
|
|
96
|
-
|
|
86
|
+
## ⚛️ React
|
|
97
87
|
|
|
98
|
-
```
|
|
99
|
-
import
|
|
100
|
-
import { SlotText
|
|
88
|
+
```tsx
|
|
89
|
+
import "slot-text/style.css";
|
|
90
|
+
import { SlotText } from "slot-text/react";
|
|
91
|
+
import { chromatic } from "slot-text";
|
|
92
|
+
|
|
93
|
+
<SlotText
|
|
94
|
+
text={copied ? "Copied" : "Copy"}
|
|
95
|
+
options={{ direction: copied ? "up" : "down", color: copied ? chromatic() : undefined }}
|
|
96
|
+
/>
|
|
101
97
|
```
|
|
102
98
|
|
|
103
|
-
|
|
99
|
+
## 💚 Vue
|
|
104
100
|
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
101
|
+
```vue
|
|
102
|
+
<script setup lang="ts">
|
|
103
|
+
import "slot-text/style.css";
|
|
104
|
+
import { SlotText } from "slot-text/vue";
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<template>
|
|
108
|
+
<SlotText text="Copied" :options="{ direction: 'up' }" />
|
|
109
|
+
</template>
|
|
111
110
|
```
|
|
112
111
|
|
|
113
|
-
##
|
|
112
|
+
## 🔷 Solid
|
|
114
113
|
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
skipUnchanged?: boolean;
|
|
126
|
-
interrupt?: boolean;
|
|
127
|
-
};
|
|
114
|
+
```tsx
|
|
115
|
+
import "slot-text/style.css";
|
|
116
|
+
import { createSignal } from "solid-js";
|
|
117
|
+
import { slotText } from "slot-text/solid";
|
|
118
|
+
|
|
119
|
+
const [label, setLabel] = createSignal("Copy");
|
|
120
|
+
|
|
121
|
+
<button aria-label={label()} onClick={() => setLabel("Copied")}>
|
|
122
|
+
<span use:slotText={{ text: label(), options: { direction: "up" } }} />
|
|
123
|
+
</button>
|
|
128
124
|
```
|
|
129
125
|
|
|
130
|
-
|
|
131
|
-
fresh. `interrupt: false` lets the current roll finish: the latest call made
|
|
132
|
-
mid-roll plays once it lands, and calls targeting the text already displayed
|
|
133
|
-
are dropped — ideal for spam-prone triggers like buttons.
|
|
126
|
+
## 🧡 Svelte
|
|
134
127
|
|
|
135
|
-
|
|
128
|
+
```svelte
|
|
129
|
+
<script lang="ts">
|
|
130
|
+
import "slot-text/style.css";
|
|
131
|
+
import { slotText } from "slot-text/svelte";
|
|
136
132
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
easing: "cubic-bezier(0.34, 1.56, 0.64, 1)",
|
|
144
|
-
bounce: 0.6,
|
|
145
|
-
colorFade: 280,
|
|
146
|
-
skipUnchanged: true,
|
|
147
|
-
interrupt: true,
|
|
148
|
-
}
|
|
133
|
+
let label = "Copy";
|
|
134
|
+
</script>
|
|
135
|
+
|
|
136
|
+
<button aria-label={label} on:click={() => label = "Copied"}>
|
|
137
|
+
<span use:slotText={{ text: label, options: { direction: "up" } }}></span>
|
|
138
|
+
</button>
|
|
149
139
|
```
|
|
150
140
|
|
|
151
|
-
##
|
|
141
|
+
## ⚙️ Options
|
|
152
142
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
143
|
+
| Option | Default | Description |
|
|
144
|
+
| --- | --- | --- |
|
|
145
|
+
| `direction` | `"down"` | Roll direction: `"up"` or `"down"` |
|
|
146
|
+
| `stagger` | `45` | Delay between characters (ms) |
|
|
147
|
+
| `duration` | `300` | Per-character animation time (ms) |
|
|
148
|
+
| `exitOffset` | `50` | Delay before the old character exits (ms) |
|
|
149
|
+
| `easing` | springy bezier | CSS easing function |
|
|
150
|
+
| `bounce` | `0.6` | Overshoot amount |
|
|
151
|
+
| `color` | — | Color string, or `(index, total) => string` |
|
|
152
|
+
| `colorFade` | `280` | Fade back to base color (ms) |
|
|
153
|
+
| `skipUnchanged` | `true` | Don't re-roll identical characters |
|
|
154
|
+
| `interrupt` | `true` | See below 👇 |
|
|
157
155
|
|
|
158
|
-
|
|
159
|
-
import "slot-text/style.css";
|
|
160
|
-
import { slotText, chromatic } from "slot-text";
|
|
156
|
+
### 🛑 `interrupt`
|
|
161
157
|
|
|
162
|
-
|
|
158
|
+
- `interrupt: true` *(default)* — cuts off any roll in flight, starts fresh.
|
|
159
|
+
- `interrupt: false` — lets the current roll **finish**; the latest call plays
|
|
160
|
+
after it lands, duplicates are dropped. Ideal for spam-prone buttons.
|
|
163
161
|
|
|
164
|
-
|
|
165
|
-
label.flash("Copied", {
|
|
166
|
-
enter: { direction: "up", skipUnchanged: false, color: chromatic() },
|
|
167
|
-
exit: { direction: "down", skipUnchanged: false },
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
</script>
|
|
171
|
-
```
|
|
162
|
+
### 🌈 `chromatic()`
|
|
172
163
|
|
|
173
|
-
|
|
164
|
+
Built-in rainbow color helper — pass it as `color` for a per-character hue sweep.
|
|
174
165
|
|
|
175
|
-
|
|
176
|
-
font you give the element — so widths are always correct.
|
|
166
|
+
## 🔤 Font support
|
|
177
167
|
|
|
178
|
-
|
|
168
|
+
Each character animates in its own measured cell using your element's exact
|
|
169
|
+
font, so widths are always correct.
|
|
179
170
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
including italics and glyphs with overhang.
|
|
171
|
+
✅ **Great with:** monospace fonts, proportional Latin / Cyrillic / Greek
|
|
172
|
+
(Geist, Inter, SF, …), italics, glyphs with overhang.
|
|
183
173
|
|
|
184
|
-
|
|
174
|
+
⚠️ **Tradeoffs** (inherent to any per-character slot animation):
|
|
185
175
|
|
|
186
|
-
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
scripts need contextual letterforms across the string and will render as
|
|
192
|
-
isolated forms.
|
|
193
|
-
- **Complex emoji split.** Single emoji are fine (surrogate pairs are
|
|
194
|
-
handled), but ZWJ sequences (👨👩👧) and combining marks break into
|
|
195
|
-
multiple cells.
|
|
196
|
-
- **Very tall display/script fonts** may clip at the vertical roll mask,
|
|
197
|
-
which is sized to `line-height: 1.3`.
|
|
176
|
+
- Kerning is lost — pairs like `AV` sit slightly looser (invisible at label sizes).
|
|
177
|
+
- Ligatures won't form (`fi`, `fl`, coding ligatures).
|
|
178
|
+
- Joined scripts (Arabic, Devanagari) render as isolated forms.
|
|
179
|
+
- ZWJ emoji sequences (👨👩👧) split into cells; single emoji are fine.
|
|
180
|
+
- Very tall display fonts may clip at the roll mask (`line-height: 1.3`).
|
|
198
181
|
|
|
199
|
-
In short
|
|
182
|
+
**In short:** ideal for short labels, numbers, statuses and commands — in
|
|
200
183
|
essentially any font you'd use for those.
|
|
201
184
|
|
|
202
|
-
## Notes
|
|
185
|
+
## 📝 Notes
|
|
203
186
|
|
|
204
|
-
- Browser-only DOM utility.
|
|
205
|
-
-
|
|
206
|
-
|
|
207
|
-
- Works best on short labels, buttons, counters, and command text.
|
|
187
|
+
- Browser-only DOM utility, zero runtime dependencies.
|
|
188
|
+
- React, Vue, Solid, and Svelte are optional peer dependencies — plain JS users
|
|
189
|
+
don't need them.
|
|
208
190
|
- Import the CSS once before using the animation.
|
|
191
|
+
- Low-level helpers also exported: `buildSlotText`, `animateSlotText`, `chromatic`.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { animateSlotText, buildSlotText, chromatic, clearSlotText, } from "./slotText.js";
|
|
2
|
-
import { animateSlotText, buildSlotText, clearSlotText
|
|
2
|
+
import { animateSlotText, buildSlotText, clearSlotText } from "./slotText.js";
|
|
3
3
|
/**
|
|
4
4
|
* Create a text-roll controller for one element.
|
|
5
5
|
*
|
package/dist/solid.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Accessor } from "solid-js";
|
|
2
|
+
import { type SlotOptions } from "./index.js";
|
|
3
|
+
export interface SlotTextParams {
|
|
4
|
+
text: string;
|
|
5
|
+
options?: SlotOptions;
|
|
6
|
+
}
|
|
7
|
+
export declare function slotText(element: HTMLElement, accessor: Accessor<SlotTextParams>): void;
|
|
8
|
+
declare module "solid-js" {
|
|
9
|
+
namespace JSX {
|
|
10
|
+
interface Directives {
|
|
11
|
+
slotText: SlotTextParams;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
package/dist/solid.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRenderEffect, onCleanup } from "solid-js";
|
|
2
|
+
import { slotText as createSlotText } from "./index.js";
|
|
3
|
+
export function slotText(element, accessor) {
|
|
4
|
+
const initial = accessor();
|
|
5
|
+
const controller = createSlotText(element, initial.text);
|
|
6
|
+
let previousText = initial.text;
|
|
7
|
+
let isFirstRun = true;
|
|
8
|
+
createRenderEffect(() => {
|
|
9
|
+
const next = accessor();
|
|
10
|
+
if (isFirstRun) {
|
|
11
|
+
isFirstRun = false;
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (next.text !== previousText) {
|
|
15
|
+
previousText = next.text;
|
|
16
|
+
controller.set(next.text, next.options);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
onCleanup(() => {
|
|
20
|
+
controller.destroy();
|
|
21
|
+
});
|
|
22
|
+
}
|
package/dist/svelte.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type SlotOptions } from "./index.js";
|
|
2
|
+
export interface SlotTextParams {
|
|
3
|
+
text: string;
|
|
4
|
+
options?: SlotOptions;
|
|
5
|
+
}
|
|
6
|
+
export declare function slotText(element: HTMLElement, params: SlotTextParams): {
|
|
7
|
+
update(params: SlotTextParams): void;
|
|
8
|
+
destroy(): void;
|
|
9
|
+
};
|
package/dist/svelte.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { slotText as createSlotText } from "./index.js";
|
|
2
|
+
export function slotText(element, params) {
|
|
3
|
+
const controller = createSlotText(element, params.text);
|
|
4
|
+
let previousText = params.text;
|
|
5
|
+
return {
|
|
6
|
+
update(params) {
|
|
7
|
+
if (params.text === previousText)
|
|
8
|
+
return;
|
|
9
|
+
previousText = params.text;
|
|
10
|
+
controller.set(params.text, params.options);
|
|
11
|
+
},
|
|
12
|
+
destroy() {
|
|
13
|
+
controller.destroy();
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "slot-text/style.css";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createSignal } from "solid-js";
|
|
2
|
+
import "slot-text/style.css";
|
|
3
|
+
import { chromatic } from "slot-text";
|
|
4
|
+
import { slotText } from "slot-text/solid";
|
|
5
|
+
|
|
6
|
+
void slotText;
|
|
7
|
+
|
|
8
|
+
export function CopyButton() {
|
|
9
|
+
const [copied, setCopied] = createSignal(false);
|
|
10
|
+
|
|
11
|
+
function copy() {
|
|
12
|
+
setCopied(true);
|
|
13
|
+
window.setTimeout(() => setCopied(false), 1400);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<button type="button" aria-label={copied() ? "Copied" : "Copy"} onClick={copy}>
|
|
18
|
+
<span
|
|
19
|
+
use:slotText={{
|
|
20
|
+
text: copied() ? "Copied" : "Copy",
|
|
21
|
+
options: {
|
|
22
|
+
direction: copied() ? "up" : "down",
|
|
23
|
+
skipUnchanged: false,
|
|
24
|
+
color: copied() ? chromatic({ from: 190 }) : undefined,
|
|
25
|
+
},
|
|
26
|
+
}}
|
|
27
|
+
/>
|
|
28
|
+
</button>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "slot-text/style.css";
|
|
3
|
+
import { chromatic } from "slot-text";
|
|
4
|
+
import { slotText } from "slot-text/svelte";
|
|
5
|
+
|
|
6
|
+
let copied = false;
|
|
7
|
+
|
|
8
|
+
function copy() {
|
|
9
|
+
copied = true;
|
|
10
|
+
window.setTimeout(() => {
|
|
11
|
+
copied = false;
|
|
12
|
+
}, 1400);
|
|
13
|
+
}
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<button type="button" aria-label={copied ? "Copied" : "Copy"} on:click={copy}>
|
|
17
|
+
<span
|
|
18
|
+
use:slotText={{
|
|
19
|
+
text: copied ? "Copied" : "Copy",
|
|
20
|
+
options: {
|
|
21
|
+
direction: copied ? "up" : "down",
|
|
22
|
+
skipUnchanged: false,
|
|
23
|
+
color: copied ? chromatic({ from: 190 }) : undefined,
|
|
24
|
+
},
|
|
25
|
+
}}
|
|
26
|
+
></span>
|
|
27
|
+
</button>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ES2020",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ES2020", "DOM"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"jsx": "preserve",
|
|
10
|
+
"jsxImportSource": "solid-js",
|
|
11
|
+
"paths": {
|
|
12
|
+
"slot-text": ["../src/index.ts"],
|
|
13
|
+
"slot-text/solid": ["../src/solid.ts"],
|
|
14
|
+
"slot-text/svelte": ["../src/svelte.ts"]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"include": ["env.d.ts", "solid.tsx", "*.svelte", "../src/**/*.ts"]
|
|
18
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slot-text",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Dependency-free text roll animation for tiny, tactile UI labels.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"dist",
|
|
14
14
|
"examples",
|
|
15
15
|
"style.css",
|
|
16
|
+
"style.css.d.ts",
|
|
16
17
|
"README.md",
|
|
17
18
|
"LICENSE"
|
|
18
19
|
],
|
|
@@ -29,11 +30,24 @@
|
|
|
29
30
|
"types": "./dist/vue.d.ts",
|
|
30
31
|
"import": "./dist/vue.js"
|
|
31
32
|
},
|
|
32
|
-
"./
|
|
33
|
+
"./solid": {
|
|
34
|
+
"types": "./dist/solid.d.ts",
|
|
35
|
+
"import": "./dist/solid.js"
|
|
36
|
+
},
|
|
37
|
+
"./svelte": {
|
|
38
|
+
"types": "./dist/svelte.d.ts",
|
|
39
|
+
"import": "./dist/svelte.js"
|
|
40
|
+
},
|
|
41
|
+
"./style.css": {
|
|
42
|
+
"types": "./style.css.d.ts",
|
|
43
|
+
"default": "./style.css"
|
|
44
|
+
}
|
|
33
45
|
},
|
|
34
46
|
"types": "./dist/index.d.ts",
|
|
35
47
|
"peerDependencies": {
|
|
36
48
|
"react": ">=18 <20",
|
|
49
|
+
"solid-js": ">=1.8 <2",
|
|
50
|
+
"svelte": ">=4 <6",
|
|
37
51
|
"vue": ">=3.4 <4"
|
|
38
52
|
},
|
|
39
53
|
"peerDependenciesMeta": {
|
|
@@ -42,17 +56,29 @@
|
|
|
42
56
|
},
|
|
43
57
|
"vue": {
|
|
44
58
|
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"solid-js": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"svelte": {
|
|
64
|
+
"optional": true
|
|
45
65
|
}
|
|
46
66
|
},
|
|
47
67
|
"scripts": {
|
|
68
|
+
"prepublishOnly": "npm run build",
|
|
48
69
|
"build": "tsc -p tsconfig.json",
|
|
49
70
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
50
|
-
"pack:check": "npm pack --dry-run"
|
|
71
|
+
"pack:check": "npm pack --dry-run",
|
|
72
|
+
"test": "vitest run"
|
|
51
73
|
},
|
|
52
74
|
"devDependencies": {
|
|
53
75
|
"@types/react": "^19.2.17",
|
|
76
|
+
"happy-dom": "^20.10.2",
|
|
54
77
|
"react": "^19.2.7",
|
|
78
|
+
"solid-js": "^1.9.13",
|
|
79
|
+
"svelte": "^5.56.3",
|
|
55
80
|
"typescript": "^5.8.3",
|
|
81
|
+
"vitest": "^4.1.8",
|
|
56
82
|
"vue": "^3.5.35"
|
|
57
83
|
}
|
|
58
84
|
}
|
package/style.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.slot-text {
|
|
2
2
|
display: inline-flex;
|
|
3
3
|
white-space: pre;
|
|
4
|
+
align-items: baseline;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
.char-slot {
|
|
@@ -12,6 +13,7 @@
|
|
|
12
13
|
instead of letting the row overflow like it does at rest. */
|
|
13
14
|
flex: none;
|
|
14
15
|
justify-content: center;
|
|
16
|
+
align-items: baseline;
|
|
15
17
|
/* Clip only vertically: the roll needs a top/bottom mask, but glyph side
|
|
16
18
|
bearings, kerning overhang and the settle tilt must stay visible so
|
|
17
19
|
letters never look cropped. (overflow: hidden is the legacy fallback.) */
|
|
@@ -19,7 +21,6 @@
|
|
|
19
21
|
overflow-x: visible;
|
|
20
22
|
overflow-y: clip;
|
|
21
23
|
line-height: 1.3;
|
|
22
|
-
vertical-align: bottom;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/* Cells appearing from or collapsing to empty change width drastically, so
|
package/style.css.d.ts
ADDED