@uibit/text-rotator 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UIBit Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Text Rotator
2
+
3
+ [Interactive Demonstration](https://rawlings.github.io/uibit/components/text-rotator)
4
+
5
+ Text Rotator cycles through an array of phrases inside a static sentence. It transitions between list items using vertical slide or 3D perspective flip animations, designed to highlight shifting value propositions within a compact, responsive boundary.
6
+
7
+ ## Value Delivery
8
+
9
+ - **Dynamic Value Propositions** – Allows websites to cycle through key selling points, features, or target markets within a single headline, saving visual space.
10
+ - **Controlled Motion** – Focuses animation exclusively on changing phrases, ensuring layouts do not move or shift as content sizes vary.
11
+ - **Refined Customization** – Offers customizable slide and flip transitions, control speed intervals, and styling properties that align with brand themes.
12
+
13
+ ## Ideal Applications
14
+
15
+ - **Headline Value Statements** – Displaying phrases like "We build [performant / accessible / beautiful] components" on homepage banners.
16
+ - **Product Feature Lists** – Highlighting changing use cases or target audiences in marketing sections.
17
+ - **Key Metrics Rotators** – Displaying rotating callouts or statistics in a space-saving headline.
18
+
19
+ ## Further Information
20
+
21
+ Detailed design guidelines, customizable attributes, and integration examples are available on our documentation site.
22
+
23
+ ## Changelog
24
+
25
+ Please see the [Changelog](CHANGELOG.md) for version history.
@@ -0,0 +1,303 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/index.ts",
8
+ "declarations": [],
9
+ "exports": [
10
+ {
11
+ "kind": "js",
12
+ "name": "default",
13
+ "declaration": {
14
+ "name": "default",
15
+ "module": "./text-rotator"
16
+ }
17
+ },
18
+ {
19
+ "kind": "js",
20
+ "name": "TextRotator",
21
+ "declaration": {
22
+ "name": "TextRotator",
23
+ "module": "./text-rotator"
24
+ }
25
+ },
26
+ {
27
+ "kind": "js",
28
+ "name": "*",
29
+ "declaration": {
30
+ "name": "*",
31
+ "module": "src/types"
32
+ }
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "kind": "javascript-module",
38
+ "path": "src/styles.ts",
39
+ "declarations": [
40
+ {
41
+ "kind": "variable",
42
+ "name": "styles",
43
+ "default": "css` :host { display: inline-block; vertical-align: text-bottom; font-size: var(--uibit-text-rotator-font-size, inherit); font-weight: var(--uibit-text-rotator-font-weight, inherit); color: var(--uibit-text-rotator-color, inherit); font-family: var(--uibit-text-rotator-font-family, inherit); line-height: var(--uibit-text-rotator-line-height, inherit); /* Pad the host horizontally to prevent clipping of long words, pull back with margin */ padding: 0 4rem; margin: 0 -4rem; } .stage { display: inline-block; position: relative; width: max-content; min-width: 1ch; perspective: 20rem; transform-style: preserve-3d; /* Pad stage vertically to allow fade mask space above/below line box */ padding: 1em 0; margin: -1em 0; /* Mask only the rotating words inside the stage */ -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 1em, #000 calc(100% - 1em), transparent 100%); mask-image: linear-gradient(to bottom, transparent 0%, #000 1em, #000 calc(100% - 1em), transparent 100%); -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; } .word { display: inline-block; position: absolute; top: 1em; /* Align absolute words to stage content-box */ left: 0; white-space: nowrap; transform-style: preserve-3d; } .word.active { position: relative; top: 0; } /* No animation on first render */ .word.initial { position: static; opacity: 1; } /* Slide */ .word.entering-slide { animation: slide-in var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards; } .word.leaving-slide { animation: slide-out var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards; } /* Flip */ .word.entering-flip { animation: flip-in var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards; transform-origin: 50% 0; } .word.leaving-flip { animation: flip-out var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards; transform-origin: 50% 100%; } @keyframes slide-in { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes slide-out { from { transform: translateY(0); opacity: 1; } to { transform: translateY(-100%); opacity: 0; } } @keyframes flip-in { from { transform: rotateX(-80deg); opacity: 0; } to { transform: rotateX(0deg); opacity: 1; } } @keyframes flip-out { from { transform: rotateX(0deg); opacity: 1; } to { transform: rotateX(80deg); opacity: 0; } } `"
44
+ }
45
+ ],
46
+ "exports": [
47
+ {
48
+ "kind": "js",
49
+ "name": "styles",
50
+ "declaration": {
51
+ "name": "styles",
52
+ "module": "src/styles.ts"
53
+ }
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ "kind": "javascript-module",
59
+ "path": "src/text-rotator.ts",
60
+ "declarations": [
61
+ {
62
+ "kind": "class",
63
+ "description": "Cycles through an array of phrases inside a static sentence by animating between\nitems with a vertical slide or 3D flip transition. Designed to highlight changing\nvalue propositions without motion outside the component boundary.\n\nPass static prefix or wrapper text inside the default slot, and phrases to cycle through\ninside elements with `slot=\"text\"` (e.g. `<span slot=\"text\">phrase</span>`).",
64
+ "name": "TextRotator",
65
+ "cssProperties": [
66
+ {
67
+ "description": "Font size",
68
+ "name": "--uibit-text-rotator-font-size",
69
+ "default": "inherit"
70
+ },
71
+ {
72
+ "description": "Font weight",
73
+ "name": "--uibit-text-rotator-font-weight",
74
+ "default": "inherit"
75
+ },
76
+ {
77
+ "description": "Text color",
78
+ "name": "--uibit-text-rotator-color",
79
+ "default": "inherit"
80
+ },
81
+ {
82
+ "description": "Font family",
83
+ "name": "--uibit-text-rotator-font-family",
84
+ "default": "inherit"
85
+ },
86
+ {
87
+ "description": "Line height",
88
+ "name": "--uibit-text-rotator-line-height",
89
+ "default": "inherit"
90
+ },
91
+ {
92
+ "description": "Transition animation duration",
93
+ "name": "--uibit-text-rotator-duration",
94
+ "default": "0.4s"
95
+ }
96
+ ],
97
+ "members": [
98
+ {
99
+ "kind": "field",
100
+ "name": "words",
101
+ "type": {
102
+ "text": "string[]"
103
+ },
104
+ "privacy": "private",
105
+ "default": "[]"
106
+ },
107
+ {
108
+ "kind": "field",
109
+ "name": "interval",
110
+ "type": {
111
+ "text": "number"
112
+ },
113
+ "default": "2500",
114
+ "description": "Interval in ms between rotations.",
115
+ "attribute": "interval"
116
+ },
117
+ {
118
+ "kind": "field",
119
+ "name": "transition",
120
+ "type": {
121
+ "text": "'slide' | 'flip'"
122
+ },
123
+ "default": "'slide'",
124
+ "description": "Transition style: 'slide' for vertical slide, 'flip' for 3D perspective flip.",
125
+ "attribute": "transition"
126
+ },
127
+ {
128
+ "kind": "field",
129
+ "name": "loop",
130
+ "type": {
131
+ "text": "boolean"
132
+ },
133
+ "default": "true",
134
+ "description": "Loop indefinitely. Set to false to stop after the last word.",
135
+ "attribute": "loop"
136
+ },
137
+ {
138
+ "kind": "field",
139
+ "name": "_activeIndex",
140
+ "type": {
141
+ "text": "number"
142
+ },
143
+ "privacy": "private",
144
+ "default": "0"
145
+ },
146
+ {
147
+ "kind": "field",
148
+ "name": "_prevIndex",
149
+ "type": {
150
+ "text": "number"
151
+ },
152
+ "privacy": "private",
153
+ "default": "-1"
154
+ },
155
+ {
156
+ "kind": "field",
157
+ "name": "_animating",
158
+ "type": {
159
+ "text": "boolean"
160
+ },
161
+ "privacy": "private",
162
+ "default": "false"
163
+ },
164
+ {
165
+ "kind": "field",
166
+ "name": "_mounted",
167
+ "type": {
168
+ "text": "boolean"
169
+ },
170
+ "privacy": "private",
171
+ "default": "false"
172
+ },
173
+ {
174
+ "kind": "field",
175
+ "name": "_timer",
176
+ "type": {
177
+ "text": "ReturnType<typeof setInterval> | undefined"
178
+ },
179
+ "privacy": "private"
180
+ },
181
+ {
182
+ "kind": "method",
183
+ "name": "_start",
184
+ "privacy": "private"
185
+ },
186
+ {
187
+ "kind": "method",
188
+ "name": "_advance",
189
+ "privacy": "private"
190
+ },
191
+ {
192
+ "kind": "method",
193
+ "name": "_parseCssDuration",
194
+ "privacy": "private",
195
+ "return": {
196
+ "type": {
197
+ "text": "number"
198
+ }
199
+ },
200
+ "parameters": [
201
+ {
202
+ "name": "val",
203
+ "type": {
204
+ "text": "string"
205
+ }
206
+ }
207
+ ]
208
+ },
209
+ {
210
+ "kind": "method",
211
+ "name": "_handleSlotChange",
212
+ "privacy": "private",
213
+ "parameters": [
214
+ {
215
+ "name": "e",
216
+ "type": {
217
+ "text": "Event"
218
+ }
219
+ }
220
+ ]
221
+ }
222
+ ],
223
+ "events": [
224
+ {
225
+ "type": {
226
+ "text": "{ word: string, index: number }"
227
+ },
228
+ "description": "Fired when the active word changes",
229
+ "name": "word-change"
230
+ }
231
+ ],
232
+ "attributes": [
233
+ {
234
+ "name": "interval",
235
+ "type": {
236
+ "text": "number"
237
+ },
238
+ "default": "2500",
239
+ "description": "Interval in ms between rotations.",
240
+ "fieldName": "interval"
241
+ },
242
+ {
243
+ "name": "transition",
244
+ "type": {
245
+ "text": "'slide' | 'flip'"
246
+ },
247
+ "default": "'slide'",
248
+ "description": "Transition style: 'slide' for vertical slide, 'flip' for 3D perspective flip.",
249
+ "fieldName": "transition"
250
+ },
251
+ {
252
+ "name": "loop",
253
+ "type": {
254
+ "text": "boolean"
255
+ },
256
+ "default": "true",
257
+ "description": "Loop indefinitely. Set to false to stop after the last word.",
258
+ "fieldName": "loop"
259
+ }
260
+ ],
261
+ "superclass": {
262
+ "name": "UIBitElement",
263
+ "package": "@uibit/core"
264
+ },
265
+ "tagName": "uibit-text-rotator",
266
+ "customElement": true
267
+ }
268
+ ],
269
+ "exports": [
270
+ {
271
+ "kind": "js",
272
+ "name": "TextRotator",
273
+ "declaration": {
274
+ "name": "TextRotator",
275
+ "module": "src/text-rotator.ts"
276
+ }
277
+ },
278
+ {
279
+ "kind": "custom-element-definition",
280
+ "name": "uibit-text-rotator",
281
+ "declaration": {
282
+ "name": "TextRotator",
283
+ "module": "src/text-rotator.ts"
284
+ }
285
+ },
286
+ {
287
+ "kind": "js",
288
+ "name": "default",
289
+ "declaration": {
290
+ "name": "TextRotator",
291
+ "module": "src/text-rotator.ts"
292
+ }
293
+ }
294
+ ]
295
+ },
296
+ {
297
+ "kind": "javascript-module",
298
+ "path": "src/types.ts",
299
+ "declarations": [],
300
+ "exports": []
301
+ }
302
+ ]
303
+ }
@@ -0,0 +1,38 @@
1
+ import { Component, ChangeDetectionStrategy, ElementRef, input, effect, output, booleanAttribute, numberAttribute } from '@angular/core';
2
+ import '@uibit/text-rotator';
3
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
4
+
5
+ @Component({
6
+ selector: 'uibit-text-rotator',
7
+ template: '<ng-content></ng-content>',
8
+ changeDetection: ChangeDetectionStrategy.OnPush,
9
+ standalone: true,
10
+ host: {
11
+ '(word-change)': 'wordChange.emit($event)'
12
+ }
13
+ })
14
+ export class NgxTextRotator {
15
+ constructor(private el: ElementRef<HTMLElementClass>) {
16
+ effect(() => {
17
+ if (this.el.nativeElement) {
18
+ this.el.nativeElement.interval = this.interval();
19
+ }
20
+ });
21
+ effect(() => {
22
+ if (this.el.nativeElement) {
23
+ this.el.nativeElement.transition = this.transition();
24
+ }
25
+ });
26
+ effect(() => {
27
+ if (this.el.nativeElement) {
28
+ this.el.nativeElement.loop = this.loop();
29
+ }
30
+ });
31
+ }
32
+
33
+ readonly interval = input<number, any>(2500, { transform: numberAttribute });
34
+ readonly transition = input<'slide' | 'flip', any>('slide');
35
+ readonly loop = input<boolean, any>(true, { transform: booleanAttribute });
36
+
37
+ readonly wordChange = output<CustomEvent<{ word: string, index: number }>>();
38
+ }
@@ -0,0 +1,10 @@
1
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
2
+ import '@uibit/text-rotator';
3
+
4
+ declare global {
5
+ namespace astroHTML.JSX {
6
+ interface IntrinsicElements {
7
+ 'uibit-text-rotator': Partial<HTMLElementClass> & astroHTML.JSX.HTMLAttributes;
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,7 @@
1
+ import { defineNuxtPlugin } from '#app';
2
+
3
+ export default defineNuxtPlugin(() => {
4
+ if (process.client) {
5
+ import('@uibit/text-rotator');
6
+ }
7
+ });
@@ -0,0 +1,15 @@
1
+ import type { JSX } from 'preact';
2
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
3
+ import '@uibit/text-rotator';
4
+
5
+ declare module 'preact' {
6
+ namespace JSX {
7
+ interface IntrinsicElements {
8
+ 'uibit-text-rotator': JSX.HTMLAttributes<HTMLElementClass> & {
9
+ interval?: number;
10
+ transition?: 'slide' | 'flip';
11
+ loop?: boolean;
12
+ };
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ import { component$, Slot } from '@builder.io/qwik';
2
+ import '@uibit/text-rotator';
3
+
4
+ export const TextRotator = component$<any>((props) => {
5
+ return (
6
+ <uibit-text-rotator {...props}>
7
+ <Slot />
8
+ </uibit-text-rotator>
9
+ );
10
+ });
@@ -0,0 +1,20 @@
1
+ import type { HTMLAttributes, ClassAttributes } from 'react';
2
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
3
+ import '@uibit/text-rotator';
4
+
5
+ declare global {
6
+ namespace React {
7
+ namespace JSX {
8
+ interface IntrinsicElements {
9
+ 'uibit-text-rotator': ClassAttributes<HTMLElementClass> & HTMLAttributes<HTMLElementClass> & {
10
+ children?: React.ReactNode;
11
+ class?: string;
12
+ interval?: number;
13
+ transition?: 'slide' | 'flip';
14
+ loop?: boolean;
15
+ onWordChange?: (event: any) => void;
16
+ };
17
+ }
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,16 @@
1
+ import type { JSX } from 'solid-js';
2
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
3
+ import '@uibit/text-rotator';
4
+
5
+ declare module 'solid-js' {
6
+ namespace JSX {
7
+ interface IntrinsicElements {
8
+ 'uibit-text-rotator': Partial<HTMLElementClass> & JSX.HTMLAttributes<HTMLElementClass> & {
9
+ interval?: number;
10
+ transition?: 'slide' | 'flip';
11
+ loop?: boolean;
12
+ "on:word-change"?: (event: CustomEvent) => void;
13
+ };
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,14 @@
1
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
2
+ import '@uibit/text-rotator';
3
+
4
+ declare module '@stencil/core' {
5
+ export namespace JSX {
6
+ interface IntrinsicElements {
7
+ 'uibit-text-rotator': HTMLElementClass & {
8
+ interval?: number;
9
+ transition?: 'slide' | 'flip';
10
+ loop?: boolean;
11
+ };
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ import '@uibit/text-rotator';
3
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
4
+
5
+ let {
6
+ interval = undefined,
7
+ transition = undefined,
8
+ loop = undefined,
9
+ children
10
+ } = $props<{
11
+ children?: any;
12
+ interval?: number;
13
+ transition?: 'slide' | 'flip';
14
+ loop?: boolean;
15
+
16
+ }>();
17
+
18
+ let elementRef: HTMLElementClass | null = $state(null);
19
+
20
+ $effect(() => {
21
+ if (elementRef && interval !== undefined) {
22
+ elementRef.interval = interval;
23
+ }
24
+ if (elementRef && transition !== undefined) {
25
+ elementRef.transition = transition;
26
+ }
27
+ if (elementRef && loop !== undefined) {
28
+ elementRef.loop = loop;
29
+ }
30
+ });
31
+
32
+ </script>
33
+
34
+ <uibit-text-rotator bind:this={elementRef} {...$$restProps}>
35
+
36
+ {#if children}
37
+ {@render children()}
38
+ {:else}
39
+ <slot />
40
+ {/if}
41
+ </uibit-text-rotator>
@@ -0,0 +1,26 @@
1
+ import { defineComponent, h } from 'vue';
2
+ import type { TextRotator as HTMLElementClass } from '@uibit/text-rotator';
3
+ import '@uibit/text-rotator';
4
+
5
+ export const TextRotator = defineComponent({
6
+ name: 'TextRotator',
7
+ props: {
8
+ interval: { type: [String, Number, Boolean, Array, Object] as any },
9
+ transition: { type: [String, Number, Boolean, Array, Object] as any },
10
+ loop: { type: [String, Number, Boolean, Array, Object] as any }
11
+ },
12
+ emits: ['word-change'],
13
+ setup(props, { slots, emit }) {
14
+ return () => {
15
+ const eventListeners: Record<string, any> = {};
16
+ eventListeners['onWord-change'] = (event: Event) => {
17
+ emit('word-change', event);
18
+ };
19
+
20
+ return h('uibit-text-rotator', {
21
+ ...props,
22
+ ...eventListeners
23
+ }, slots.default?.());
24
+ };
25
+ }
26
+ });
@@ -0,0 +1,3 @@
1
+ export { default, TextRotator } from './text-rotator';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACtD,cAAc,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { default, TextRotator } from './text-rotator';
2
+ export * from './types';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACtD,cAAc,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ //# sourceMappingURL=styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBA6FlB,CAAC"}
package/dist/styles.js ADDED
@@ -0,0 +1,96 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: inline-block;
5
+ vertical-align: text-bottom;
6
+ font-size: var(--uibit-text-rotator-font-size, inherit);
7
+ font-weight: var(--uibit-text-rotator-font-weight, inherit);
8
+ color: var(--uibit-text-rotator-color, inherit);
9
+ font-family: var(--uibit-text-rotator-font-family, inherit);
10
+ line-height: var(--uibit-text-rotator-line-height, inherit);
11
+
12
+ /* Pad the host horizontally to prevent clipping of long words, pull back with margin */
13
+ padding: 0 4rem;
14
+ margin: 0 -4rem;
15
+ }
16
+
17
+ .stage {
18
+ display: inline-block;
19
+ position: relative;
20
+ width: max-content;
21
+ min-width: 1ch;
22
+ perspective: 20rem;
23
+ transform-style: preserve-3d;
24
+
25
+ /* Pad stage vertically to allow fade mask space above/below line box */
26
+ padding: 1em 0;
27
+ margin: -1em 0;
28
+
29
+ /* Mask only the rotating words inside the stage */
30
+ -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 1em, #000 calc(100% - 1em), transparent 100%);
31
+ mask-image: linear-gradient(to bottom, transparent 0%, #000 1em, #000 calc(100% - 1em), transparent 100%);
32
+ -webkit-mask-repeat: no-repeat;
33
+ mask-repeat: no-repeat;
34
+ }
35
+
36
+ .word {
37
+ display: inline-block;
38
+ position: absolute;
39
+ top: 1em; /* Align absolute words to stage content-box */
40
+ left: 0;
41
+ white-space: nowrap;
42
+ transform-style: preserve-3d;
43
+ }
44
+
45
+ .word.active {
46
+ position: relative;
47
+ top: 0;
48
+ }
49
+
50
+ /* No animation on first render */
51
+ .word.initial {
52
+ position: static;
53
+ opacity: 1;
54
+ }
55
+
56
+ /* Slide */
57
+ .word.entering-slide {
58
+ animation: slide-in var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards;
59
+ }
60
+
61
+ .word.leaving-slide {
62
+ animation: slide-out var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards;
63
+ }
64
+
65
+ /* Flip */
66
+ .word.entering-flip {
67
+ animation: flip-in var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards;
68
+ transform-origin: 50% 0;
69
+ }
70
+
71
+ .word.leaving-flip {
72
+ animation: flip-out var(--uibit-text-rotator-duration, 0.4s) cubic-bezier(0.4, 0, 0.2, 1) forwards;
73
+ transform-origin: 50% 100%;
74
+ }
75
+
76
+ @keyframes slide-in {
77
+ from { transform: translateY(100%); opacity: 0; }
78
+ to { transform: translateY(0); opacity: 1; }
79
+ }
80
+
81
+ @keyframes slide-out {
82
+ from { transform: translateY(0); opacity: 1; }
83
+ to { transform: translateY(-100%); opacity: 0; }
84
+ }
85
+
86
+ @keyframes flip-in {
87
+ from { transform: rotateX(-80deg); opacity: 0; }
88
+ to { transform: rotateX(0deg); opacity: 1; }
89
+ }
90
+
91
+ @keyframes flip-out {
92
+ from { transform: rotateX(0deg); opacity: 1; }
93
+ to { transform: rotateX(80deg); opacity: 0; }
94
+ }
95
+ `;
96
+ //# sourceMappingURL=styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FxB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { UIBitElement } from '@uibit/core';
2
+ /**
3
+ * Cycles through an array of phrases inside a static sentence by animating between
4
+ * items with a vertical slide or 3D flip transition. Designed to highlight changing
5
+ * value propositions without motion outside the component boundary.
6
+ *
7
+ * Pass static prefix or wrapper text inside the default slot, and phrases to cycle through
8
+ * inside elements with `slot="text"` (e.g. `<span slot="text">phrase</span>`).
9
+ *
10
+ * @fires {{ word: string, index: number }} word-change - Fired when the active word changes
11
+ *
12
+ * @cssprop [--uibit-text-rotator-font-size=inherit] - Font size
13
+ * @cssprop [--uibit-text-rotator-font-weight=inherit] - Font weight
14
+ * @cssprop [--uibit-text-rotator-color=inherit] - Text color
15
+ * @cssprop [--uibit-text-rotator-font-family=inherit] - Font family
16
+ * @cssprop [--uibit-text-rotator-line-height=inherit] - Line height
17
+ * @cssprop [--uibit-text-rotator-duration=0.4s] - Transition animation duration
18
+ */
19
+ export declare class TextRotator extends UIBitElement {
20
+ static styles: import("lit").CSSResult;
21
+ private words;
22
+ /** Interval in ms between rotations. */
23
+ interval: number;
24
+ /** Transition style: 'slide' for vertical slide, 'flip' for 3D perspective flip. */
25
+ transition: 'slide' | 'flip';
26
+ /** Loop indefinitely. Set to false to stop after the last word. */
27
+ loop: boolean;
28
+ private _activeIndex;
29
+ private _prevIndex;
30
+ private _animating;
31
+ private _mounted;
32
+ private _timer?;
33
+ connectedCallback(): void;
34
+ disconnectedCallback(): void;
35
+ firstUpdated(): void;
36
+ updated(changed: Map<string, unknown>): void;
37
+ private _start;
38
+ private _advance;
39
+ private _parseCssDuration;
40
+ private _handleSlotChange;
41
+ render(): import("lit").TemplateResult<1>;
42
+ }
43
+ export default TextRotator;
44
+ //# sourceMappingURL=text-rotator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-rotator.d.ts","sourceRoot":"","sources":["../src/text-rotator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,YAAY,EAAE,MAAM,aAAa,CAAC;AAI1D;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,WAAY,SAAQ,YAAY;IAC3C,MAAM,CAAC,MAAM,0BAAU;IAEd,OAAO,CAAC,KAAK,CAAgB;IAEtC,wCAAwC;IACZ,QAAQ,SAAQ;IAE5C,oFAAoF;IACxD,UAAU,EAAE,OAAO,GAAG,MAAM,CAAW;IAEnE,mEAAmE;IACtC,IAAI,UAAQ;IAEhC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IAElC,OAAO,CAAC,MAAM,CAAC,CAAiC;IAEhD,iBAAiB,SAGhB;IAED,oBAAoB,SAGnB;IAED,YAAY,SAGX;IAED,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,QAUpC;IAED,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,QAAQ;IAqBhB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,iBAAiB;IAWzB,MAAM,oCAaL;CACF;eAEc,WAAW"}
@@ -0,0 +1,157 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html } from 'lit';
8
+ import { keyed } from 'lit/directives/keyed.js';
9
+ import { customElement, UIBitElement } from '@uibit/core';
10
+ import { property, state } from 'lit/decorators.js';
11
+ import { styles } from './styles';
12
+ /**
13
+ * Cycles through an array of phrases inside a static sentence by animating between
14
+ * items with a vertical slide or 3D flip transition. Designed to highlight changing
15
+ * value propositions without motion outside the component boundary.
16
+ *
17
+ * Pass static prefix or wrapper text inside the default slot, and phrases to cycle through
18
+ * inside elements with `slot="text"` (e.g. `<span slot="text">phrase</span>`).
19
+ *
20
+ * @fires {{ word: string, index: number }} word-change - Fired when the active word changes
21
+ *
22
+ * @cssprop [--uibit-text-rotator-font-size=inherit] - Font size
23
+ * @cssprop [--uibit-text-rotator-font-weight=inherit] - Font weight
24
+ * @cssprop [--uibit-text-rotator-color=inherit] - Text color
25
+ * @cssprop [--uibit-text-rotator-font-family=inherit] - Font family
26
+ * @cssprop [--uibit-text-rotator-line-height=inherit] - Line height
27
+ * @cssprop [--uibit-text-rotator-duration=0.4s] - Transition animation duration
28
+ */
29
+ let TextRotator = class TextRotator extends UIBitElement {
30
+ constructor() {
31
+ super(...arguments);
32
+ this.words = [];
33
+ /** Interval in ms between rotations. */
34
+ this.interval = 2500;
35
+ /** Transition style: 'slide' for vertical slide, 'flip' for 3D perspective flip. */
36
+ this.transition = 'slide';
37
+ /** Loop indefinitely. Set to false to stop after the last word. */
38
+ this.loop = true;
39
+ this._activeIndex = 0;
40
+ this._prevIndex = -1;
41
+ this._animating = false;
42
+ this._mounted = false;
43
+ }
44
+ static { this.styles = styles; }
45
+ connectedCallback() {
46
+ super.connectedCallback();
47
+ this._start();
48
+ }
49
+ disconnectedCallback() {
50
+ super.disconnectedCallback();
51
+ clearInterval(this._timer);
52
+ }
53
+ firstUpdated() {
54
+ // Mark as mounted so the first word renders without an enter animation
55
+ requestAnimationFrame(() => { this._mounted = true; });
56
+ }
57
+ updated(changed) {
58
+ if (changed.has('words') && this.words.length) {
59
+ clearInterval(this._timer);
60
+ this._activeIndex = 0;
61
+ this._prevIndex = -1;
62
+ this._animating = false;
63
+ this._mounted = false;
64
+ requestAnimationFrame(() => { this._mounted = true; });
65
+ this._start();
66
+ }
67
+ }
68
+ _start() {
69
+ if (!this.words.length)
70
+ return;
71
+ this._timer = setInterval(() => this._advance(), this.interval);
72
+ }
73
+ _advance() {
74
+ if (this._animating || !this.words.length)
75
+ return;
76
+ const next = (this._activeIndex + 1) % this.words.length;
77
+ if (!this.loop && next === 0) {
78
+ clearInterval(this._timer);
79
+ return;
80
+ }
81
+ this._animating = true;
82
+ this._prevIndex = this._activeIndex;
83
+ this._activeIndex = next;
84
+ this.dispatchCustomEvent('word-change', { word: this.words[this._activeIndex], index: this._activeIndex });
85
+ const durationStr = this.getCssPropertyValue('--uibit-text-rotator-duration') || '0.4s';
86
+ const dur = this._parseCssDuration(durationStr);
87
+ setTimeout(() => {
88
+ this._prevIndex = -1;
89
+ this._animating = false;
90
+ }, dur + 50);
91
+ }
92
+ _parseCssDuration(val) {
93
+ const trimmed = val.trim();
94
+ if (!trimmed)
95
+ return 400;
96
+ if (trimmed.endsWith('ms')) {
97
+ return parseFloat(trimmed);
98
+ }
99
+ if (trimmed.endsWith('s')) {
100
+ return parseFloat(trimmed) * 1000;
101
+ }
102
+ return parseFloat(trimmed) || 400;
103
+ }
104
+ _handleSlotChange(e) {
105
+ const slot = e.target;
106
+ const nodes = slot.assignedNodes({ flatten: true });
107
+ const words = nodes
108
+ .map(node => node.textContent?.trim() ?? '')
109
+ .filter(text => text !== '');
110
+ if (words.length > 0) {
111
+ this.words = words;
112
+ }
113
+ }
114
+ render() {
115
+ const t = this.transition;
116
+ const activeWord = this.words[this._activeIndex] ?? '';
117
+ const prevWord = this._prevIndex >= 0 ? this.words[this._prevIndex] : null;
118
+ return html `
119
+ <slot></slot>
120
+ <slot name="text" @slotchange=${this._handleSlotChange} style="display: none;"></slot>
121
+ <span class="stage">
122
+ ${prevWord !== null ? html `<span class="word leaving-${t}" aria-hidden="true">${prevWord}</span>` : ''}
123
+ ${keyed(this._activeIndex, html `<span class="word ${this._mounted ? `entering-${t}` : 'initial'} active">${activeWord}</span>`)}
124
+ </span>
125
+ `;
126
+ }
127
+ };
128
+ __decorate([
129
+ state()
130
+ ], TextRotator.prototype, "words", void 0);
131
+ __decorate([
132
+ property({ type: Number })
133
+ ], TextRotator.prototype, "interval", void 0);
134
+ __decorate([
135
+ property({ type: String })
136
+ ], TextRotator.prototype, "transition", void 0);
137
+ __decorate([
138
+ property({ type: Boolean })
139
+ ], TextRotator.prototype, "loop", void 0);
140
+ __decorate([
141
+ state()
142
+ ], TextRotator.prototype, "_activeIndex", void 0);
143
+ __decorate([
144
+ state()
145
+ ], TextRotator.prototype, "_prevIndex", void 0);
146
+ __decorate([
147
+ state()
148
+ ], TextRotator.prototype, "_animating", void 0);
149
+ __decorate([
150
+ state()
151
+ ], TextRotator.prototype, "_mounted", void 0);
152
+ TextRotator = __decorate([
153
+ customElement('uibit-text-rotator')
154
+ ], TextRotator);
155
+ export { TextRotator };
156
+ export default TextRotator;
157
+ //# sourceMappingURL=text-rotator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-rotator.js","sourceRoot":"","sources":["../src/text-rotator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type TextRotator from './text-rotator';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'uibit-text-rotator': TextRotator;
5
+ }
6
+ }
7
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAE9C,OAAO,CAAC,MAAM,CAAC;IACf,UAAU,qBAAqB;QAC3B,oBAAoB,EAAE,WAAW,CAAC;KACrC;CACA"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,89 @@
1
+ {
2
+ "name": "@uibit/text-rotator",
3
+ "version": "0.1.0",
4
+ "description": "Rotates a single word inside a static sentence block with smooth vertical slide or 3D flip transitions. Designed to pull attention to changing value propositions.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./custom-elements.json": "./custom-elements.json",
14
+ "./react": "./dist/frameworks/react/index.d.ts",
15
+ "./vue": "./dist/frameworks/vue/index.ts",
16
+ "./svelte": "./dist/frameworks/svelte/index.svelte",
17
+ "./angular": "./dist/frameworks/angular/index.ts",
18
+ "./solid": "./dist/frameworks/solid/index.d.ts",
19
+ "./astro": "./dist/frameworks/astro/index.astro",
20
+ "./qwik": "./dist/frameworks/qwik/index.tsx",
21
+ "./nuxt": "./dist/frameworks/nuxt/index.ts",
22
+ "./preact": "./dist/frameworks/preact/index.d.ts",
23
+ "./stencil": "./dist/frameworks/stencil/index.d.ts"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "package.json",
28
+ "README.md",
29
+ "LICENSE",
30
+ "custom-elements.json"
31
+ ],
32
+ "keywords": [
33
+ "text-rotator",
34
+ "animation",
35
+ "marketing",
36
+ "web-component",
37
+ "lit"
38
+ ],
39
+ "author": "Jonathan Rawlings",
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/Rawlings/uibit",
44
+ "directory": "packages/components/text-rotator"
45
+ },
46
+ "dependencies": {
47
+ "@uibit/core": "0.1.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^20.19.43",
51
+ "lit": "^3.3.3",
52
+ "typescript": "7.0.2",
53
+ "@uibit/codegen": "0.1.0"
54
+ },
55
+ "peerDependencies": {
56
+ "lit": "^3.0.0",
57
+ "react": ">=18",
58
+ "vue": ">=3",
59
+ "svelte": ">=4 || ^5",
60
+ "@angular/core": ">=14"
61
+ },
62
+ "customElements": "custom-elements.json",
63
+ "peerDependenciesMeta": {
64
+ "react": {
65
+ "optional": true
66
+ },
67
+ "vue": {
68
+ "optional": true
69
+ },
70
+ "svelte": {
71
+ "optional": true
72
+ },
73
+ "@angular/core": {
74
+ "optional": true
75
+ }
76
+ },
77
+ "uibit": {
78
+ "id": "text-rotator",
79
+ "title": "Text Rotator",
80
+ "category": "Text",
81
+ "tagName": "uibit-text-rotator"
82
+ },
83
+ "scripts": {
84
+ "build": "cem analyze --globs 'src/**/*.ts' --litelement && uibit-codegen --package . && tsc",
85
+ "dev": "concurrently \"cem analyze --globs 'src/**/*.ts' --litelement --watch\" \"tsc --watch\"",
86
+ "analyze": "cem analyze --globs 'src/**/*.ts' --litelement",
87
+ "typecheck": "tsc --noEmit"
88
+ }
89
+ }