@uibit/read-time 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 +21 -0
- package/README.md +22 -0
- package/custom-elements.json +244 -0
- package/dist/frameworks/angular/index.ts +27 -0
- package/dist/frameworks/astro/index.d.ts +10 -0
- package/dist/frameworks/nuxt/index.ts +7 -0
- package/dist/frameworks/preact/index.d.ts +14 -0
- package/dist/frameworks/qwik/index.tsx +10 -0
- package/dist/frameworks/react/index.d.ts +18 -0
- package/dist/frameworks/solid/index.d.ts +15 -0
- package/dist/frameworks/stencil/index.d.ts +13 -0
- package/dist/frameworks/svelte/index.svelte +41 -0
- package/dist/frameworks/vue/index.ts +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/read-time.d.ts +36 -0
- package/dist/read-time.d.ts.map +1 -0
- package/dist/read-time.js +133 -0
- package/dist/read-time.js.map +1 -0
- package/dist/styles.d.ts +2 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +36 -0
- package/dist/styles.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 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,22 @@
|
|
|
1
|
+
# Text Read Timer
|
|
2
|
+
|
|
3
|
+
[Interactive Demonstration](https://rawlings.github.io/uibit/text-read-timer)
|
|
4
|
+
|
|
5
|
+
Text Read Timer automatically analyzes document length and displays a reading time estimate to users. By calculating read times directly on the client, it helps readers set expectations before committing to long-form articles, improving retention rates and page loyalty.
|
|
6
|
+
|
|
7
|
+
## Value Delivery
|
|
8
|
+
|
|
9
|
+
- **Improved Engagement** – Transparent reading estimates give readers context, reducing bounce rates on detailed pages.
|
|
10
|
+
- **Client-Side Calculation** – Counts words and estimates reading durations in real-time on the client side, eliminating backend plugins or metadata fields.
|
|
11
|
+
- **Flexible Integration** – Renders dynamically as a badge, with support for custom slotting so that the timer can be positioned anywhere within article bylines or headers.
|
|
12
|
+
- **Adjustable Parameters** – Supports configurable words-per-minute calibrations to accommodate different audiences and languages.
|
|
13
|
+
|
|
14
|
+
## Ideal Applications
|
|
15
|
+
|
|
16
|
+
- **Editorial Platforms & Blogs** – Displaying read times in article summaries, headers, and indexes.
|
|
17
|
+
- **Documentation Sites** – Providing guides and tutorials with clear completion timeframes.
|
|
18
|
+
- **Knowledge Bases** – Helping users locate quick-read answers or detailed guides.
|
|
19
|
+
|
|
20
|
+
## Further Information
|
|
21
|
+
|
|
22
|
+
Detailed design guidelines, customizable attributes, and integration examples are available on our documentation site.
|
|
@@ -0,0 +1,244 @@
|
|
|
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": "./read-time"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"kind": "js",
|
|
20
|
+
"name": "ReadTime",
|
|
21
|
+
"declaration": {
|
|
22
|
+
"name": "ReadTime",
|
|
23
|
+
"module": "./read-time"
|
|
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/read-time.ts",
|
|
39
|
+
"declarations": [
|
|
40
|
+
{
|
|
41
|
+
"kind": "class",
|
|
42
|
+
"description": "Analyzes the word count of its slotted content and renders a reading-time\nbadge. The calculation happens inside the shadow DOM via a slot\nchange observer — no backend metadata required.\n\nPlace your HTML content in the default slot. The component counts only text\nnodes, ignoring markup and hidden elements.",
|
|
43
|
+
"name": "ReadTime",
|
|
44
|
+
"cssProperties": [
|
|
45
|
+
{
|
|
46
|
+
"description": "Badge font size",
|
|
47
|
+
"name": "--uibit-read-time-font-size",
|
|
48
|
+
"default": "0.8125rem"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"description": "Badge font weight",
|
|
52
|
+
"name": "--uibit-read-time-font-weight",
|
|
53
|
+
"default": "500"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"description": "Badge text color",
|
|
57
|
+
"name": "--uibit-read-time-color",
|
|
58
|
+
"default": "#6b7280"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"description": "Badge font family",
|
|
62
|
+
"name": "--uibit-read-time-font-family",
|
|
63
|
+
"default": "inherit"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"description": "Gap between icon and label",
|
|
67
|
+
"name": "--uibit-read-time-gap",
|
|
68
|
+
"default": "0.375rem"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"description": "Size of the clock icon",
|
|
72
|
+
"name": "--uibit-read-time-icon-size",
|
|
73
|
+
"default": "0.875rem"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"description": "Color of the clock icon",
|
|
77
|
+
"name": "--uibit-read-time-icon-color",
|
|
78
|
+
"default": "currentColor"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"slots": [
|
|
82
|
+
{
|
|
83
|
+
"description": "The content whose text will be measured",
|
|
84
|
+
"name": ""
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"description": "Optional named slot to position or override the read-time label/badge",
|
|
88
|
+
"name": "timer"
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
"members": [
|
|
92
|
+
{
|
|
93
|
+
"kind": "field",
|
|
94
|
+
"name": "wpm",
|
|
95
|
+
"type": {
|
|
96
|
+
"text": "number"
|
|
97
|
+
},
|
|
98
|
+
"default": "238",
|
|
99
|
+
"description": "Average reading speed in words per minute.",
|
|
100
|
+
"attribute": "wpm"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"kind": "field",
|
|
104
|
+
"name": "showIcon",
|
|
105
|
+
"type": {
|
|
106
|
+
"text": "boolean"
|
|
107
|
+
},
|
|
108
|
+
"default": "true",
|
|
109
|
+
"description": "Show the clock icon before the label.",
|
|
110
|
+
"attribute": "show-icon"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"kind": "field",
|
|
114
|
+
"name": "_label",
|
|
115
|
+
"type": {
|
|
116
|
+
"text": "string"
|
|
117
|
+
},
|
|
118
|
+
"privacy": "private",
|
|
119
|
+
"default": "''"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"kind": "field",
|
|
123
|
+
"name": "_slot",
|
|
124
|
+
"type": {
|
|
125
|
+
"text": "HTMLSlotElement | undefined"
|
|
126
|
+
},
|
|
127
|
+
"privacy": "private"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"kind": "field",
|
|
131
|
+
"name": "_timerSlot",
|
|
132
|
+
"type": {
|
|
133
|
+
"text": "HTMLSlotElement | undefined"
|
|
134
|
+
},
|
|
135
|
+
"privacy": "private"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"kind": "method",
|
|
139
|
+
"name": "_calculate",
|
|
140
|
+
"privacy": "private"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"kind": "method",
|
|
144
|
+
"name": "_extractText",
|
|
145
|
+
"privacy": "private",
|
|
146
|
+
"return": {
|
|
147
|
+
"type": {
|
|
148
|
+
"text": "string"
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"parameters": [
|
|
152
|
+
{
|
|
153
|
+
"name": "node",
|
|
154
|
+
"type": {
|
|
155
|
+
"text": "Node"
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"attributes": [
|
|
162
|
+
{
|
|
163
|
+
"name": "wpm",
|
|
164
|
+
"type": {
|
|
165
|
+
"text": "number"
|
|
166
|
+
},
|
|
167
|
+
"default": "238",
|
|
168
|
+
"description": "Average reading speed in words per minute.",
|
|
169
|
+
"fieldName": "wpm"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "show-icon",
|
|
173
|
+
"type": {
|
|
174
|
+
"text": "boolean"
|
|
175
|
+
},
|
|
176
|
+
"default": "true",
|
|
177
|
+
"description": "Show the clock icon before the label.",
|
|
178
|
+
"fieldName": "showIcon"
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
"superclass": {
|
|
182
|
+
"name": "UIBitElement",
|
|
183
|
+
"package": "@uibit/core"
|
|
184
|
+
},
|
|
185
|
+
"tagName": "uibit-read-time",
|
|
186
|
+
"customElement": true
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"exports": [
|
|
190
|
+
{
|
|
191
|
+
"kind": "js",
|
|
192
|
+
"name": "ReadTime",
|
|
193
|
+
"declaration": {
|
|
194
|
+
"name": "ReadTime",
|
|
195
|
+
"module": "src/read-time.ts"
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"kind": "custom-element-definition",
|
|
200
|
+
"name": "uibit-read-time",
|
|
201
|
+
"declaration": {
|
|
202
|
+
"name": "ReadTime",
|
|
203
|
+
"module": "src/read-time.ts"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"kind": "js",
|
|
208
|
+
"name": "default",
|
|
209
|
+
"declaration": {
|
|
210
|
+
"name": "ReadTime",
|
|
211
|
+
"module": "src/read-time.ts"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"kind": "javascript-module",
|
|
218
|
+
"path": "src/styles.ts",
|
|
219
|
+
"declarations": [
|
|
220
|
+
{
|
|
221
|
+
"kind": "variable",
|
|
222
|
+
"name": "styles",
|
|
223
|
+
"default": "css` :host { display: block; font-family: var(--uibit-read-time-font-family, inherit); } .timer { display: inline-flex; align-items: center; gap: var(--uibit-read-time-gap, 0.375rem); font-size: var(--uibit-read-time-font-size, var(--uibit-font-size-sm, 0.8125rem)); font-weight: var(--uibit-read-time-font-weight, var(--uibit-font-weight-medium, 500)); color: var(--uibit-read-time-color, #6b7280); line-height: var(--uibit-line-height-normal, 1.5); } .icon { display: inline-flex; align-items: center; flex-shrink: 0; color: var(--uibit-read-time-icon-color, currentColor); width: var(--uibit-read-time-icon-size, 0.875rem); height: var(--uibit-read-time-icon-size, 0.875rem); } .icon svg { width: 100%; height: 100%; } .label { white-space: nowrap; } `"
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
"exports": [
|
|
227
|
+
{
|
|
228
|
+
"kind": "js",
|
|
229
|
+
"name": "styles",
|
|
230
|
+
"declaration": {
|
|
231
|
+
"name": "styles",
|
|
232
|
+
"module": "src/styles.ts"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"kind": "javascript-module",
|
|
239
|
+
"path": "src/types.ts",
|
|
240
|
+
"declarations": [],
|
|
241
|
+
"exports": []
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Component, ChangeDetectionStrategy, ElementRef, input, effect, booleanAttribute, numberAttribute } from '@angular/core';
|
|
2
|
+
import '@uibit/read-time';
|
|
3
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
@Component({
|
|
6
|
+
selector: 'uibit-read-time',
|
|
7
|
+
template: '<ng-content></ng-content>',
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
standalone: true
|
|
10
|
+
})
|
|
11
|
+
export class NgxReadTime {
|
|
12
|
+
constructor(private el: ElementRef<HTMLElementClass>) {
|
|
13
|
+
effect(() => {
|
|
14
|
+
if (this.el.nativeElement) {
|
|
15
|
+
this.el.nativeElement.wpm = this.wpm();
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
effect(() => {
|
|
19
|
+
if (this.el.nativeElement) {
|
|
20
|
+
this.el.nativeElement.showIcon = this.showIcon();
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
readonly wpm = input<number, any>(238, { transform: numberAttribute });
|
|
26
|
+
readonly showIcon = input<boolean, any>(true, { transform: booleanAttribute });
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
2
|
+
import '@uibit/read-time';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
namespace astroHTML.JSX {
|
|
6
|
+
interface IntrinsicElements {
|
|
7
|
+
'uibit-read-time': Partial<HTMLElementClass> & astroHTML.JSX.HTMLAttributes;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { JSX } from 'preact';
|
|
2
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
3
|
+
import '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
declare module 'preact' {
|
|
6
|
+
namespace JSX {
|
|
7
|
+
interface IntrinsicElements {
|
|
8
|
+
'uibit-read-time': JSX.HTMLAttributes<HTMLElementClass> & {
|
|
9
|
+
wpm?: number;
|
|
10
|
+
showIcon?: boolean;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HTMLAttributes, ClassAttributes } from 'react';
|
|
2
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
3
|
+
import '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
namespace React {
|
|
7
|
+
namespace JSX {
|
|
8
|
+
interface IntrinsicElements {
|
|
9
|
+
'uibit-read-time': ClassAttributes<HTMLElementClass> & HTMLAttributes<HTMLElementClass> & {
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
class?: string;
|
|
12
|
+
wpm?: number;
|
|
13
|
+
showIcon?: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JSX } from 'solid-js';
|
|
2
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
3
|
+
import '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
declare module 'solid-js' {
|
|
6
|
+
namespace JSX {
|
|
7
|
+
interface IntrinsicElements {
|
|
8
|
+
'uibit-read-time': Partial<HTMLElementClass> & JSX.HTMLAttributes<HTMLElementClass> & {
|
|
9
|
+
wpm?: number;
|
|
10
|
+
showIcon?: boolean;
|
|
11
|
+
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
2
|
+
import '@uibit/read-time';
|
|
3
|
+
|
|
4
|
+
declare module '@stencil/core' {
|
|
5
|
+
export namespace JSX {
|
|
6
|
+
interface IntrinsicElements {
|
|
7
|
+
'uibit-read-time': HTMLElementClass & {
|
|
8
|
+
wpm?: number;
|
|
9
|
+
showIcon?: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import '@uibit/read-time';
|
|
3
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
wpm = undefined,
|
|
7
|
+
showIcon = undefined,
|
|
8
|
+
timer = undefined,
|
|
9
|
+
children
|
|
10
|
+
} = $props<{
|
|
11
|
+
children?: any;
|
|
12
|
+
wpm?: number;
|
|
13
|
+
showIcon?: boolean;
|
|
14
|
+
timer?: import('svelte').Snippet;
|
|
15
|
+
}>();
|
|
16
|
+
|
|
17
|
+
let elementRef: HTMLElementClass | null = $state(null);
|
|
18
|
+
|
|
19
|
+
$effect(() => {
|
|
20
|
+
if (elementRef && wpm !== undefined) {
|
|
21
|
+
elementRef.wpm = wpm;
|
|
22
|
+
}
|
|
23
|
+
if (elementRef && showIcon !== undefined) {
|
|
24
|
+
elementRef.showIcon = showIcon;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<uibit-read-time bind:this={elementRef} {...$$restProps}>
|
|
31
|
+
{#if timer}
|
|
32
|
+
<div slot="timer">
|
|
33
|
+
{@render timer()}
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
36
|
+
{#if children}
|
|
37
|
+
{@render children()}
|
|
38
|
+
{:else}
|
|
39
|
+
<slot />
|
|
40
|
+
{/if}
|
|
41
|
+
</uibit-read-time>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineComponent, h } from 'vue';
|
|
2
|
+
import type { ReadTime as HTMLElementClass } from '@uibit/read-time';
|
|
3
|
+
import '@uibit/read-time';
|
|
4
|
+
|
|
5
|
+
export const ReadTime = defineComponent({
|
|
6
|
+
name: 'ReadTime',
|
|
7
|
+
props: {
|
|
8
|
+
wpm: { type: [String, Number, Boolean, Array, Object] as any },
|
|
9
|
+
showIcon: { type: [String, Number, Boolean, Array, Object] as any }
|
|
10
|
+
},
|
|
11
|
+
emits: [],
|
|
12
|
+
setup(props, { slots, emit }) {
|
|
13
|
+
return () => {
|
|
14
|
+
const eventListeners: Record<string, any> = {};
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
return h('uibit-read-time', {
|
|
18
|
+
...props,
|
|
19
|
+
...eventListeners
|
|
20
|
+
}, slots.default?.());
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAChD,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAChD,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { UIBitElement } from '@uibit/core';
|
|
2
|
+
/**
|
|
3
|
+
* Analyzes the word count of its slotted content and renders a reading-time
|
|
4
|
+
* badge. The calculation happens inside the shadow DOM via a slot
|
|
5
|
+
* change observer — no backend metadata required.
|
|
6
|
+
*
|
|
7
|
+
* Place your HTML content in the default slot. The component counts only text
|
|
8
|
+
* nodes, ignoring markup and hidden elements.
|
|
9
|
+
*
|
|
10
|
+
* @slot - The content whose text will be measured
|
|
11
|
+
* @slot timer - Optional named slot to position or override the read-time label/badge
|
|
12
|
+
*
|
|
13
|
+
* @cssprop [--uibit-read-time-font-size=0.8125rem] - Badge font size
|
|
14
|
+
* @cssprop [--uibit-read-time-font-weight=500] - Badge font weight
|
|
15
|
+
* @cssprop [--uibit-read-time-color=#6b7280] - Badge text color
|
|
16
|
+
* @cssprop [--uibit-read-time-font-family=inherit] - Badge font family
|
|
17
|
+
* @cssprop [--uibit-read-time-gap=0.375rem] - Gap between icon and label
|
|
18
|
+
* @cssprop [--uibit-read-time-icon-size=0.875rem] - Size of the clock icon
|
|
19
|
+
* @cssprop [--uibit-read-time-icon-color=currentColor] - Color of the clock icon
|
|
20
|
+
*/
|
|
21
|
+
export declare class ReadTime extends UIBitElement {
|
|
22
|
+
static styles: import("lit").CSSResult;
|
|
23
|
+
/** Average reading speed in words per minute. */
|
|
24
|
+
wpm: number;
|
|
25
|
+
/** Show the clock icon before the label. */
|
|
26
|
+
showIcon: boolean;
|
|
27
|
+
private _label;
|
|
28
|
+
private _slot?;
|
|
29
|
+
private _timerSlot?;
|
|
30
|
+
firstUpdated(): void;
|
|
31
|
+
private _calculate;
|
|
32
|
+
private _extractText;
|
|
33
|
+
render(): import("lit").TemplateResult<1>;
|
|
34
|
+
}
|
|
35
|
+
export default ReadTime;
|
|
36
|
+
//# sourceMappingURL=read-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-time.d.ts","sourceRoot":"","sources":["../src/read-time.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,YAAY,EAAY,MAAM,aAAa,CAAC;AAKzF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,QAAS,SAAQ,YAAY;IACxC,MAAM,CAAC,MAAM,0BAAU;IAEvB,iDAAiD;IACH,GAAG,SAAO;IACxD,4CAA4C;IACS,QAAQ,UAAQ;IAE5D,OAAO,CAAC,MAAM,CAAM;IAE7B,OAAO,CAAC,KAAK,CAAC,CAAkB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAkB;IAErC,YAAY,SAQX;IAED,OAAO,CAAC,UAAU;IA0ClB,OAAO,CAAC,YAAY;IAkBpB,MAAM,oCAUL;CACF;eAEc,QAAQ"}
|
|
@@ -0,0 +1,133 @@
|
|
|
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 { customElement, fromLucide, getIcon, UIBitElement, msg, str } from '@uibit/core';
|
|
9
|
+
import { Clock } from 'lucide';
|
|
10
|
+
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { styles } from './styles';
|
|
12
|
+
/**
|
|
13
|
+
* Analyzes the word count of its slotted content and renders a reading-time
|
|
14
|
+
* badge. The calculation happens inside the shadow DOM via a slot
|
|
15
|
+
* change observer — no backend metadata required.
|
|
16
|
+
*
|
|
17
|
+
* Place your HTML content in the default slot. The component counts only text
|
|
18
|
+
* nodes, ignoring markup and hidden elements.
|
|
19
|
+
*
|
|
20
|
+
* @slot - The content whose text will be measured
|
|
21
|
+
* @slot timer - Optional named slot to position or override the read-time label/badge
|
|
22
|
+
*
|
|
23
|
+
* @cssprop [--uibit-read-time-font-size=0.8125rem] - Badge font size
|
|
24
|
+
* @cssprop [--uibit-read-time-font-weight=500] - Badge font weight
|
|
25
|
+
* @cssprop [--uibit-read-time-color=#6b7280] - Badge text color
|
|
26
|
+
* @cssprop [--uibit-read-time-font-family=inherit] - Badge font family
|
|
27
|
+
* @cssprop [--uibit-read-time-gap=0.375rem] - Gap between icon and label
|
|
28
|
+
* @cssprop [--uibit-read-time-icon-size=0.875rem] - Size of the clock icon
|
|
29
|
+
* @cssprop [--uibit-read-time-icon-color=currentColor] - Color of the clock icon
|
|
30
|
+
*/
|
|
31
|
+
let ReadTime = class ReadTime extends UIBitElement {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(...arguments);
|
|
34
|
+
/** Average reading speed in words per minute. */
|
|
35
|
+
this.wpm = 238;
|
|
36
|
+
/** Show the clock icon before the label. */
|
|
37
|
+
this.showIcon = true;
|
|
38
|
+
this._label = '';
|
|
39
|
+
}
|
|
40
|
+
static { this.styles = styles; }
|
|
41
|
+
firstUpdated() {
|
|
42
|
+
this._slot = this.shadowRoot?.querySelector('slot:not([name])');
|
|
43
|
+
this._slot?.addEventListener('slotchange', () => this._calculate());
|
|
44
|
+
this._timerSlot = this.shadowRoot?.querySelector('slot[name="timer"]');
|
|
45
|
+
this._timerSlot?.addEventListener('slotchange', () => this._calculate());
|
|
46
|
+
this._calculate();
|
|
47
|
+
}
|
|
48
|
+
_calculate() {
|
|
49
|
+
if (!this._slot)
|
|
50
|
+
return;
|
|
51
|
+
const assigned = this._slot.assignedNodes({ flatten: true });
|
|
52
|
+
let text = '';
|
|
53
|
+
for (const node of assigned) {
|
|
54
|
+
text += this._extractText(node);
|
|
55
|
+
}
|
|
56
|
+
const words = text.trim().split(/\s+/).filter(Boolean).length;
|
|
57
|
+
const minutes = Math.ceil(words / this.wpm);
|
|
58
|
+
const timeStr = minutes < 1 ? msg('less than 1 min') : msg(str `${minutes} min`);
|
|
59
|
+
const defaultLabel = minutes < 1 ? msg('Less than 1 min read') : msg(str `${minutes} min read`);
|
|
60
|
+
this._label = defaultLabel;
|
|
61
|
+
// Update any slotted elements inside slot="timer"
|
|
62
|
+
if (this._timerSlot) {
|
|
63
|
+
const assignedTimer = this._timerSlot.assignedElements({ flatten: true });
|
|
64
|
+
for (const el of assignedTimer) {
|
|
65
|
+
let template = el.getAttribute('data-template');
|
|
66
|
+
if (template === null) {
|
|
67
|
+
const rawText = el.textContent || '';
|
|
68
|
+
if (rawText.includes('{time}')) {
|
|
69
|
+
template = rawText;
|
|
70
|
+
el.setAttribute('data-template', template);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
template = '';
|
|
74
|
+
el.setAttribute('data-template', '');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (template) {
|
|
78
|
+
el.textContent = template.replace('{time}', timeStr);
|
|
79
|
+
}
|
|
80
|
+
else if (!el.textContent || el.textContent.trim() === '' || el.hasAttribute('data-auto-update')) {
|
|
81
|
+
el.textContent = this._label;
|
|
82
|
+
el.setAttribute('data-auto-update', '');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.dispatchCustomEvent('read-time-change', { words, minutes });
|
|
87
|
+
}
|
|
88
|
+
_extractText(node) {
|
|
89
|
+
if (node.nodeType === Node.TEXT_NODE)
|
|
90
|
+
return node.textContent || '';
|
|
91
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
92
|
+
const el = node;
|
|
93
|
+
// Skip the timer slot itself if it happens to be nested or queried
|
|
94
|
+
if (el.getAttribute('slot') === 'timer')
|
|
95
|
+
return '';
|
|
96
|
+
const style = window.getComputedStyle(el);
|
|
97
|
+
if (style.display === 'none' || style.visibility === 'hidden')
|
|
98
|
+
return '';
|
|
99
|
+
let t = '';
|
|
100
|
+
for (const child of Array.from(el.childNodes)) {
|
|
101
|
+
t += this._extractText(child);
|
|
102
|
+
}
|
|
103
|
+
return t;
|
|
104
|
+
}
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
render() {
|
|
108
|
+
return html `
|
|
109
|
+
<slot name="timer">
|
|
110
|
+
<div class="timer" part="timer">
|
|
111
|
+
${this.showIcon ? html `<span class="icon" part="icon">${getIcon('clock', 14, fromLucide(Clock))}</span>` : ''}
|
|
112
|
+
<span class="label" part="label">${this._label}</span>
|
|
113
|
+
</div>
|
|
114
|
+
</slot>
|
|
115
|
+
<slot></slot>
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
__decorate([
|
|
120
|
+
property({ type: Number, attribute: 'wpm' })
|
|
121
|
+
], ReadTime.prototype, "wpm", void 0);
|
|
122
|
+
__decorate([
|
|
123
|
+
property({ type: Boolean, attribute: 'show-icon' })
|
|
124
|
+
], ReadTime.prototype, "showIcon", void 0);
|
|
125
|
+
__decorate([
|
|
126
|
+
state()
|
|
127
|
+
], ReadTime.prototype, "_label", void 0);
|
|
128
|
+
ReadTime = __decorate([
|
|
129
|
+
customElement('uibit-read-time')
|
|
130
|
+
], ReadTime);
|
|
131
|
+
export { ReadTime };
|
|
132
|
+
export default ReadTime;
|
|
133
|
+
//# sourceMappingURL=read-time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-time.js","sourceRoot":"","sources":["../src/read-time.ts"],"names":[],"mappings":"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"}
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAiClB,CAAC"}
|
package/dist/styles.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
export const styles = css `
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
font-family: var(--uibit-read-time-font-family, inherit);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.timer {
|
|
9
|
+
display: inline-flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: var(--uibit-read-time-gap, 0.375rem);
|
|
12
|
+
font-size: var(--uibit-read-time-font-size, var(--uibit-font-size-sm, 0.8125rem));
|
|
13
|
+
font-weight: var(--uibit-read-time-font-weight, var(--uibit-font-weight-medium, 500));
|
|
14
|
+
color: var(--uibit-read-time-color, #6b7280);
|
|
15
|
+
line-height: var(--uibit-line-height-normal, 1.5);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.icon {
|
|
19
|
+
display: inline-flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
flex-shrink: 0;
|
|
22
|
+
color: var(--uibit-read-time-icon-color, currentColor);
|
|
23
|
+
width: var(--uibit-read-time-icon-size, 0.875rem);
|
|
24
|
+
height: var(--uibit-read-time-icon-size, 0.875rem);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.icon svg {
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.label {
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCxB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAC;AAExC,OAAO,CAAC,MAAM,CAAC;IACf,UAAU,qBAAqB;QAC3B,iBAAiB,EAAE,QAAQ,CAAC;KAC/B;CACA"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@uibit/read-time",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Text-analyzer badge that scans the word count of its slotted content and outputs an estimated reading time string. No backend metadata required — works directly in any CMS template.",
|
|
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
|
+
"reading-time",
|
|
34
|
+
"text-analysis",
|
|
35
|
+
"badge",
|
|
36
|
+
"cms",
|
|
37
|
+
"web-component",
|
|
38
|
+
"lit"
|
|
39
|
+
],
|
|
40
|
+
"author": "Jonathan Rawlings",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/Rawlings/uibit",
|
|
45
|
+
"directory": "packages/components/read-time"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"lucide": "^1.24.0",
|
|
49
|
+
"@uibit/core": "0.1.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^20.19.43",
|
|
53
|
+
"lit": "^3.3.3",
|
|
54
|
+
"typescript": "7.0.2",
|
|
55
|
+
"@uibit/codegen": "0.1.0"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"lit": "^3.0.0",
|
|
59
|
+
"react": ">=18",
|
|
60
|
+
"vue": ">=3",
|
|
61
|
+
"svelte": ">=4 || ^5",
|
|
62
|
+
"@angular/core": ">=14"
|
|
63
|
+
},
|
|
64
|
+
"customElements": "custom-elements.json",
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"react": {
|
|
67
|
+
"optional": true
|
|
68
|
+
},
|
|
69
|
+
"vue": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"svelte": {
|
|
73
|
+
"optional": true
|
|
74
|
+
},
|
|
75
|
+
"@angular/core": {
|
|
76
|
+
"optional": true
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"uibit": {
|
|
80
|
+
"id": "read-time",
|
|
81
|
+
"title": "Read Time",
|
|
82
|
+
"category": "Text",
|
|
83
|
+
"tagName": "uibit-read-time"
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"build": "cem analyze --globs 'src/**/*.ts' --litelement && uibit-codegen --package . && tsc",
|
|
87
|
+
"dev": "concurrently \"cem analyze --globs 'src/**/*.ts' --litelement --watch\" \"tsc --watch\"",
|
|
88
|
+
"analyze": "cem analyze --globs 'src/**/*.ts' --litelement",
|
|
89
|
+
"typecheck": "tsc --noEmit"
|
|
90
|
+
}
|
|
91
|
+
}
|