godown 3.0.0-canary.7 → 3.0.0-canary.8

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.
Files changed (142) hide show
  1. package/components/alert.d.ts.map +1 -1
  2. package/components/alert.js +3 -2
  3. package/components/alert.js.map +1 -1
  4. package/components/breath.js +2 -2
  5. package/components/breath.js.map +1 -1
  6. package/components/card.d.ts +1 -1
  7. package/components/card.d.ts.map +1 -1
  8. package/components/card.js +3 -4
  9. package/components/card.js.map +1 -1
  10. package/components/carousel.js +1 -1
  11. package/components/carousel.js.map +1 -1
  12. package/components/input.d.ts +0 -1
  13. package/components/input.d.ts.map +1 -1
  14. package/components/input.js +0 -3
  15. package/components/input.js.map +1 -1
  16. package/components/layout.d.ts +1 -1
  17. package/components/layout.d.ts.map +1 -1
  18. package/components/layout.js +5 -6
  19. package/components/layout.js.map +1 -1
  20. package/components/router.js +1 -1
  21. package/components/router.js.map +1 -1
  22. package/components/select.d.ts +0 -4
  23. package/components/select.d.ts.map +1 -1
  24. package/components/select.js +0 -7
  25. package/components/select.js.map +1 -1
  26. package/components/skeleton.d.ts.map +1 -1
  27. package/components/skeleton.js +1 -2
  28. package/components/skeleton.js.map +1 -1
  29. package/components/split.d.ts +1 -1
  30. package/components/split.d.ts.map +1 -1
  31. package/components/split.js +8 -2
  32. package/components/split.js.map +1 -1
  33. package/components/text.js +1 -1
  34. package/components/text.js.map +1 -1
  35. package/core/super-input.d.ts +0 -1
  36. package/core/super-input.d.ts.map +1 -1
  37. package/core/super-input.js +0 -3
  38. package/core/super-input.js.map +1 -1
  39. package/custom-elements.json +1 -1
  40. package/dev/components/alert.d.ts.map +1 -1
  41. package/dev/components/alert.js +3 -2
  42. package/dev/components/alert.js.map +1 -1
  43. package/dev/components/breath.d.ts.map +1 -1
  44. package/dev/components/breath.js +2 -1
  45. package/dev/components/breath.js.map +1 -1
  46. package/dev/components/card.d.ts +1 -1
  47. package/dev/components/card.d.ts.map +1 -1
  48. package/dev/components/card.js +3 -4
  49. package/dev/components/card.js.map +1 -1
  50. package/dev/components/carousel.d.ts.map +1 -1
  51. package/dev/components/carousel.js +1 -0
  52. package/dev/components/carousel.js.map +1 -1
  53. package/dev/components/input.d.ts +0 -1
  54. package/dev/components/input.d.ts.map +1 -1
  55. package/dev/components/input.js +0 -3
  56. package/dev/components/input.js.map +1 -1
  57. package/dev/components/layout.d.ts +1 -1
  58. package/dev/components/layout.d.ts.map +1 -1
  59. package/dev/components/layout.js +7 -6
  60. package/dev/components/layout.js.map +1 -1
  61. package/dev/components/router.js +1 -1
  62. package/dev/components/router.js.map +1 -1
  63. package/dev/components/select.d.ts +0 -4
  64. package/dev/components/select.d.ts.map +1 -1
  65. package/dev/components/select.js +0 -7
  66. package/dev/components/select.js.map +1 -1
  67. package/dev/components/skeleton.d.ts.map +1 -1
  68. package/dev/components/skeleton.js +1 -2
  69. package/dev/components/skeleton.js.map +1 -1
  70. package/dev/components/split.d.ts +1 -1
  71. package/dev/components/split.d.ts.map +1 -1
  72. package/dev/components/split.js +9 -3
  73. package/dev/components/split.js.map +1 -1
  74. package/dev/components/text.js +3 -3
  75. package/dev/core/super-input.d.ts +0 -1
  76. package/dev/core/super-input.d.ts.map +1 -1
  77. package/dev/core/super-input.js +0 -3
  78. package/dev/core/super-input.js.map +1 -1
  79. package/package.json +7 -6
  80. package/src/alert.ts +11 -0
  81. package/src/avatar.ts +11 -0
  82. package/src/breath.ts +13 -0
  83. package/src/button.ts +11 -0
  84. package/src/card.ts +11 -0
  85. package/src/carousel.ts +11 -0
  86. package/src/components/alert.ts +282 -0
  87. package/src/components/avatar.ts +93 -0
  88. package/src/components/breath.ts +151 -0
  89. package/src/components/button.ts +276 -0
  90. package/src/components/card.ts +85 -0
  91. package/src/components/carousel.ts +166 -0
  92. package/src/components/details.ts +112 -0
  93. package/src/components/dialog.ts +160 -0
  94. package/src/components/divider.ts +44 -0
  95. package/src/components/dragbox.ts +126 -0
  96. package/src/components/flex.ts +65 -0
  97. package/src/components/form.ts +83 -0
  98. package/src/components/grid.ts +66 -0
  99. package/src/components/input.ts +71 -0
  100. package/src/components/layout.ts +84 -0
  101. package/src/components/link.ts +36 -0
  102. package/src/components/progress.ts +101 -0
  103. package/src/components/range.ts +409 -0
  104. package/src/components/rotate.ts +92 -0
  105. package/src/components/router.ts +264 -0
  106. package/src/components/select.ts +268 -0
  107. package/src/components/skeleton.ts +116 -0
  108. package/src/components/split.ts +190 -0
  109. package/src/components/switch.ts +176 -0
  110. package/src/components/text.ts +95 -0
  111. package/src/components/time.ts +77 -0
  112. package/src/components/tooltip.ts +118 -0
  113. package/src/components/typewriter.ts +147 -0
  114. package/src/core/global-style.ts +86 -0
  115. package/src/core/super-anchor.ts +52 -0
  116. package/src/core/super-input.ts +230 -0
  117. package/src/core/super-openable.ts +51 -0
  118. package/src/details.ts +11 -0
  119. package/src/dialog.ts +11 -0
  120. package/src/divider.ts +11 -0
  121. package/src/dragbox.ts +11 -0
  122. package/src/flex.ts +11 -0
  123. package/src/form.ts +11 -0
  124. package/src/grid.ts +11 -0
  125. package/src/index.ts +28 -0
  126. package/src/input.ts +13 -0
  127. package/src/layout.ts +12 -0
  128. package/src/link.ts +13 -0
  129. package/src/progress.ts +12 -0
  130. package/src/range.ts +13 -0
  131. package/src/rotate.ts +13 -0
  132. package/src/router.ts +12 -0
  133. package/src/select.ts +13 -0
  134. package/src/skeleton.ts +13 -0
  135. package/src/split.ts +13 -0
  136. package/src/switch.ts +13 -0
  137. package/src/text.ts +13 -0
  138. package/src/time.ts +13 -0
  139. package/src/tooltip.ts +13 -0
  140. package/src/typewriter.ts +11 -0
  141. package/vscode.html-custom-data.json +1 -1
  142. package/web-types.json +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "godown",
3
- "version": "3.0.0-canary.7",
3
+ "version": "3.0.0-canary.8",
4
4
  "description": "Simple, stylized, semantic web components",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -27,9 +27,9 @@
27
27
  "fmtime": "^0.0.3",
28
28
  "lit": "^3.0.0",
29
29
  "tslib": "^2.7.0",
30
- "@godown/colors": "^0.0.0",
31
- "@godown/f7-icon": "^0.0.2",
32
- "@godown/element": "^0.0.2"
30
+ "@godown/colors": "^0.0.1",
31
+ "@godown/element": "^0.0.3",
32
+ "@godown/f7-icon": "^0.0.3"
33
33
  },
34
34
  "publishConfig": {
35
35
  "access": "public"
@@ -38,7 +38,8 @@
38
38
  "**/*.{js,d.ts}+(|.map)",
39
39
  "custom-elements.json",
40
40
  "web-types.json",
41
- "vscode.{css,html}-custom-data.json"
41
+ "vscode.{css,html}-custom-data.json",
42
+ "src"
42
43
  ],
43
44
  "custom-elements": "./custom-elements.json",
44
45
  "customElements": "./custom-elements.json",
@@ -50,7 +51,7 @@
50
51
  "build": "tsc && tsx build.ts",
51
52
  "build:ts": "tsc",
52
53
  "fmt": "dprint fmt",
53
- "lint": "eslint --fix",
54
+ "lint": "eslint . --fix",
54
55
  "manifest": "tsx manifest.ts"
55
56
  }
56
57
  }
package/src/alert.ts ADDED
@@ -0,0 +1,11 @@
1
+ import Alert from "./components/alert.js";
2
+
3
+ Alert.define();
4
+
5
+ export default Alert;
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "godown-alert": Alert;
10
+ }
11
+ }
package/src/avatar.ts ADDED
@@ -0,0 +1,11 @@
1
+ import Avatar from "./components/avatar.js";
2
+
3
+ Avatar.define();
4
+
5
+ export default Avatar;
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "godown-avatar": Avatar;
10
+ }
11
+ }
package/src/breath.ts ADDED
@@ -0,0 +1,13 @@
1
+ import Breath from "./components/breath.js";
2
+
3
+ Breath.define();
4
+
5
+ export default Breath;
6
+
7
+ export * from "./components/breath.js";
8
+
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ "godown-breath": Breath;
12
+ }
13
+ }
package/src/button.ts ADDED
@@ -0,0 +1,11 @@
1
+ import Button from "./components/button.js";
2
+
3
+ Button.define();
4
+
5
+ export default Button;
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "godown-button": Button;
10
+ }
11
+ }
package/src/card.ts ADDED
@@ -0,0 +1,11 @@
1
+ import Card from "./components/card.js";
2
+
3
+ Card.define();
4
+
5
+ export default Card;
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "godown-card": Card;
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ import Carousel from "./components/carousel.js";
2
+
3
+ Carousel.define();
4
+
5
+ export default Carousel;
6
+
7
+ declare global {
8
+ interface HTMLElementTagNameMap {
9
+ "godown-carousel": Carousel;
10
+ }
11
+ }
@@ -0,0 +1,282 @@
1
+ import { godown } from "@godown/element/decorators/godown.js";
2
+ import { styles } from "@godown/element/decorators/styles.js";
3
+ import { htmlSlot } from "@godown/element/directives/html-slot.js";
4
+ import { htmlStyle } from "@godown/element/directives/html-style.js";
5
+ import { constructCSSObject, toVar } from "@godown/element/tools/css.js";
6
+ import iconCheckAltCircle from "@godown/f7-icon/icons/checkmark-alt-circle.js";
7
+ import iconExclamationCircle from "@godown/f7-icon/icons/exclamationmark-circle.js";
8
+ import iconInfoCircle from "@godown/f7-icon/icons/info-circle.js";
9
+ import iconLightbulb from "@godown/f7-icon/icons/lightbulb.js";
10
+ import iconQuestionCircle from "@godown/f7-icon/icons/question-circle.js";
11
+ import iconSlashCircle from "@godown/f7-icon/icons/slash-circle.js";
12
+ import iconXmark from "@godown/f7-icon/icons/xmark.js";
13
+ import iconXmarkCircle from "@godown/f7-icon/icons/xmark-circle.js";
14
+ import { css, html } from "lit";
15
+ import { property } from "lit/decorators.js";
16
+
17
+ import { cssGlobalVars, GlobalStyle, scopePrefix } from "../core/global-style.js";
18
+
19
+ const protoName = "alert";
20
+ const cssScope = scopePrefix(protoName);
21
+
22
+ const vars = ["color", "background"].map((v) => `${cssScope}--${v}`);
23
+
24
+ const genDark = (key: string) => {
25
+ return [cssGlobalVars._colors[key][5], cssGlobalVars._colors[key][9]];
26
+ };
27
+
28
+ const darkStyles = constructCSSObject(
29
+ vars,
30
+ {
31
+ green: genDark("green"),
32
+ blue: genDark("blue"),
33
+ orange: genDark("orange"),
34
+ red: genDark("red"),
35
+ yellow: genDark("yellow"),
36
+ purple: genDark("purple"),
37
+ teal: genDark("teal"),
38
+ pink: genDark("pink"),
39
+ gray: [cssGlobalVars._colors.lightgray[5], cssGlobalVars._colors.darkgray[5]],
40
+ white: [cssGlobalVars._colors.lightgray[2], cssGlobalVars._colors.darkgray[7]],
41
+ black: [cssGlobalVars._colors.darkgray[8], cssGlobalVars._colors.lightgray[5]],
42
+ },
43
+ () => `:host`,
44
+ (prop) => toVar(prop),
45
+ );
46
+
47
+ const genLight = (key: string) => {
48
+ return [cssGlobalVars._colors[key][6], cssGlobalVars._colors[key][0]];
49
+ };
50
+
51
+ const lightStyles = constructCSSObject(
52
+ vars,
53
+ {
54
+ green: genLight("green"),
55
+ blue: genLight("blue"),
56
+ orange: genLight("orange"),
57
+ red: genLight("red"),
58
+ yellow: genLight("yellow"),
59
+ purple: genLight("purple"),
60
+ teal: genLight("teal"),
61
+ pink: genLight("pink"),
62
+ gray: [cssGlobalVars._colors.darkgray[5], cssGlobalVars._colors.lightgray[7]],
63
+ white: [cssGlobalVars._colors.lightgray[0], cssGlobalVars._colors.darkgray[0]],
64
+ black: [cssGlobalVars._colors.darkgray[7], cssGlobalVars._colors.lightgray[3]],
65
+ },
66
+ () => `:host`,
67
+ (prop) => toVar(prop),
68
+ );
69
+
70
+ const calls = {
71
+ tip: {
72
+ color: "teal",
73
+ icon: iconLightbulb,
74
+ },
75
+ success: {
76
+ color: "green",
77
+ icon: iconCheckAltCircle,
78
+ },
79
+ info: {
80
+ color: "blue",
81
+ icon: iconInfoCircle,
82
+ },
83
+ warning: {
84
+ color: "orange",
85
+ icon: iconExclamationCircle,
86
+ },
87
+ danger: {
88
+ color: "red",
89
+ icon: iconXmarkCircle,
90
+ },
91
+ error: {
92
+ color: "red",
93
+ icon: iconXmarkCircle,
94
+ },
95
+ help: {
96
+ color: "purple",
97
+ icon: iconQuestionCircle,
98
+ },
99
+ deprecated: {
100
+ color: "gray",
101
+ icon: iconSlashCircle,
102
+ },
103
+ };
104
+
105
+ /**
106
+ * {@linkcode Alert} renders a alert.
107
+ *
108
+ * Color defaults to blue.
109
+ *
110
+ * @slot - Alert content.
111
+ * @slot title - Alert title.
112
+ * @slot icon - Alert icon.
113
+ * @category feedback
114
+ */
115
+ @godown(protoName)
116
+ @styles(
117
+ css`
118
+ :host {
119
+ border-radius: var(${cssScope}--border-radius);
120
+ ${cssScope}--border-radius: .25em;
121
+ ${cssScope}--border-width: .075em;
122
+ ${cssScope}--blockquote-width: .2em;
123
+ ${cssScope}--padding: .5em;
124
+ display: block;
125
+ width: 100%;
126
+ }
127
+
128
+ [part="root"] {
129
+ --color: var(${cssScope}--color);
130
+ color: var(--color);
131
+ width: 100%;
132
+ transition: 0.25s;
133
+ display: flex;
134
+ justify-content: space-between;
135
+ padding: var(${cssScope}--padding);
136
+ border-radius: inherit;
137
+ border: var(${cssScope}--border-width) solid var(--color);
138
+ background: var(${cssScope}--background);
139
+ }
140
+
141
+ [variant="blockquote"] {
142
+ border-radius: 0;
143
+ border-left: var(${cssScope}--blockquote-width) solid var(--color);
144
+ border-bottom: none;
145
+ border-right: none;
146
+ border-top: none;
147
+ background: transparent;
148
+ }
149
+
150
+ [part="content"]{
151
+ color: var(--color);
152
+ }
153
+
154
+ [part="root"] {
155
+ display: grid;
156
+ align-items: center;
157
+ grid-template-columns: auto 1fr auto;
158
+ grid-template-rows: auto 1fr;
159
+ }
160
+
161
+ [part="title"] {
162
+ line-height: 2em;
163
+ }
164
+
165
+ [part="icon"] {
166
+ display: inline-grid;
167
+ align-items: center;
168
+ height: 2em;
169
+ }
170
+
171
+ [part="icon"] svg {
172
+ margin-right: .5em;
173
+ width: 1.25em;
174
+ height: 1.25em;
175
+ }
176
+
177
+ [part="content"] {
178
+ grid-row: span 2 / span 2;
179
+ line-height: 1.5em;
180
+ }
181
+ `,
182
+ )
183
+ class Alert extends GlobalStyle {
184
+ /**
185
+ * If it is a legal value, the icon and preset color will be rendered.
186
+ */
187
+ @property()
188
+ call: "tip" | "success" | "info" | "warning" | "danger" | "error" | "help" | "deprecated";
189
+
190
+ /**
191
+ * The tone of the component.
192
+ * Overrides the color of the call.
193
+ */
194
+ @property()
195
+ color:
196
+ | "white"
197
+ | "black"
198
+ | "gray"
199
+ | "green"
200
+ | "teal"
201
+ | "blue"
202
+ | "red"
203
+ | "purple"
204
+ | "orange"
205
+ | "yellow"
206
+ | "pink"
207
+ | "none" = "blue";
208
+
209
+ /**
210
+ * Close delay, if 0, it will not be closed automatically.
211
+ */
212
+ @property({ type: Number })
213
+ autoclose = 0;
214
+
215
+ /**
216
+ * The title is bold and the icon height is the same as it.
217
+ */
218
+ @property()
219
+ title: string;
220
+
221
+ /**
222
+ * Content, if zero value, will be rendered as an unnamed slot.
223
+ */
224
+ @property()
225
+ content: string;
226
+
227
+ /**
228
+ * Set true to hide the close button.
229
+ *
230
+ * The behavior may change due to the {@linkcode variant} property.
231
+ */
232
+ @property({ type: Boolean })
233
+ hideClose = false;
234
+
235
+ /**
236
+ * Alert variant, if set to `blockquote`, the alert will be rendered as a blockquote.
237
+ *
238
+ * If variant is `"blockquote"`, hide the close button.
239
+ */
240
+ @property()
241
+ variant: "blockquote" | "dark" | "light" = "dark";
242
+
243
+ protected render() {
244
+ const color = calls[this.call]?.color || this.color;
245
+ const icon = this.call ? calls[this.call].icon() : htmlSlot("icon");
246
+ return [
247
+ html`<div part="root" variant="${this.variant}">
248
+ <div part="icon">${icon}</div>
249
+ <div part="content">
250
+ <strong part="title">${this.title || htmlSlot("title")}</strong>
251
+ ${this.content || htmlSlot()}
252
+ </div>
253
+ ${
254
+ !this.hideClose && this.variant !== "blockquote"
255
+ ? html`<div part="close" tabindex=0 @click="${this.close}">${iconXmark()}</div>`
256
+ : ""
257
+ }
258
+ </div>`,
259
+ htmlStyle(this.variant === "light" ? lightStyles[color] : darkStyles[color]),
260
+ ];
261
+ }
262
+
263
+ close() {
264
+ this.remove();
265
+ this.dispatchEvent(new CustomEvent("close", { bubbles: true, composed: true }));
266
+ }
267
+
268
+ protected firstUpdated() {
269
+ if (this.autoclose) {
270
+ setTimeout(() => this.close(), this.autoclose);
271
+ }
272
+ }
273
+
274
+ static alert(root: HTMLElement, option: Partial<Alert>): Alert {
275
+ const ai = new this();
276
+ Object.assign(ai, option);
277
+ root.appendChild(ai);
278
+ return ai;
279
+ }
280
+ }
281
+
282
+ export default Alert;
@@ -0,0 +1,93 @@
1
+ import { godown, styles } from "@godown/element/decorators/index.js";
2
+ import { htmlSlot } from "@godown/element/directives/index.js";
3
+ import { css, html } from "lit";
4
+ import { property } from "lit/decorators.js";
5
+
6
+ import { GlobalStyle, scopePrefix } from "../core/global-style.js";
7
+
8
+ const protoName = "avatar";
9
+ const cssScope = scopePrefix(protoName);
10
+
11
+ /**
12
+ * {@linkcode Avatar} renders a avatar.
13
+ *
14
+ * Renders as an image if it has a src property,
15
+ * otherwise falls back to name or nameless slot.
16
+ *
17
+ * @category display
18
+ */
19
+ @godown(protoName)
20
+ @styles(
21
+ css`
22
+ :host {
23
+ ${cssScope}--size: 2em;
24
+ width: var(${cssScope}--size);
25
+ height: var(${cssScope}--size);
26
+ display: inline-block;
27
+ vertical-align: bottom;
28
+ }
29
+
30
+ :host([round]){
31
+ border-radius:50%;
32
+ }
33
+
34
+ [part="image"] {
35
+ width: 100%;
36
+ height: 100%;
37
+ object-fit: cover;
38
+ }
39
+
40
+ [part="root"] {
41
+ overflow: hidden;
42
+ position: relative;
43
+ border-radius: inherit;
44
+ width: 100%;
45
+ height: 100%;
46
+ }
47
+
48
+ [part="root"] {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ }
53
+ `,
54
+ )
55
+ class Avatar extends GlobalStyle {
56
+ /**
57
+ * Image src.
58
+ */
59
+ @property()
60
+ src: string | undefined | null;
61
+ /**
62
+ * If the image is not available, the {@linkcode Avatar.format} will be displayed.
63
+ */
64
+ @property()
65
+ name = "";
66
+
67
+ @property({ type: Boolean })
68
+ round = false;
69
+
70
+ protected render() {
71
+ return html`<div part="root">${this._renderAvatar()}</div>`;
72
+ }
73
+
74
+ private _renderAvatar() {
75
+ if (this.src) {
76
+ return html`<img part="image" src="${this.src}" @error=${this._handleError} alt="${this.name}">`;
77
+ }
78
+ if (this.name) {
79
+ return html`<span part="name">${this.format()}</span>`;
80
+ }
81
+ return htmlSlot();
82
+ }
83
+
84
+ format() {
85
+ return this.name;
86
+ }
87
+
88
+ _handleError() {
89
+ this.src = undefined;
90
+ }
91
+ }
92
+
93
+ export default Avatar;
@@ -0,0 +1,151 @@
1
+ import { godown } from "@godown/element/decorators/godown.js";
2
+ import { styles } from "@godown/element/decorators/styles.js";
3
+ import { htmlStyle } from "@godown/element/directives/html-style.js";
4
+ import { css, html } from "lit";
5
+ import { property } from "lit/decorators.js";
6
+
7
+ import { cssGlobalVars, GlobalStyle, scopePrefix } from "../core/global-style.js";
8
+
9
+ const defineName = "breath";
10
+ const cssScope = scopePrefix(defineName);
11
+
12
+ /**
13
+ * {@linkcode Breath} render the text with a breathing effect.
14
+ *
15
+ * Dynamically generate a breathing effect based on the length of the split text.
16
+ *
17
+ * If there is not enough CSS variable, overrun elements will use the.
18
+ *
19
+ * godown was a css library in its earliest days,
20
+ * and this is the component version of its first effect.
21
+ *
22
+ * Inspired by Vercel home page (2023).
23
+ *
24
+ * @category effect
25
+ */
26
+ @godown(defineName)
27
+ @styles(
28
+ css`
29
+ :host {
30
+ ${cssScope}--deg: 60deg;
31
+ ${cssScope}--1-1: var(${cssGlobalVars._colors.red[5]});
32
+ ${cssScope}--1-2: var(${cssGlobalVars._colors.yellow[5]});
33
+ ${cssScope}--2-1: var(${cssGlobalVars._colors.green[5]});
34
+ ${cssScope}--2-2: var(${cssGlobalVars._colors.purple[5]});
35
+ ${cssScope}--3-1: var(${cssGlobalVars._colors.blue[5]});
36
+ ${cssScope}--3-2: var(${cssGlobalVars._colors.pink[5]});
37
+ ${cssScope}--1: linear-gradient(var(${cssScope}--deg), var(${cssScope}--1-1), var(${cssScope}--1-2));
38
+ ${cssScope}--2: linear-gradient(var(${cssScope}--deg), var(${cssScope}--2-1), var(${cssScope}--2-2));
39
+ ${cssScope}--3: linear-gradient(var(${cssScope}--deg), var(${cssScope}--3-1), var(${cssScope}--3-2));
40
+ }
41
+ `,
42
+ css`
43
+ :host {
44
+ display: flex;
45
+ margin: auto;
46
+ width: -moz-fit-content;
47
+ width: fit-content;
48
+ font-size: 2em;
49
+ align-items: center;
50
+ direction: ltr;
51
+ }
52
+
53
+ ::selection {
54
+ background: none;
55
+ }
56
+
57
+ .rel {
58
+ position: relative;
59
+ font-weight: 800;
60
+ font-size: inherit;
61
+ letter-spacing: -0.05em;
62
+ }
63
+ `,
64
+ css`
65
+ .nocolor,
66
+ .colorful {
67
+ padding: 0 0.05em;
68
+ box-sizing: border-box;
69
+ display: inline-block;
70
+ animation-iteration-count: infinite;
71
+ -webkit-text-fill-color: transparent;
72
+ -webkit-background-clip: text !important;
73
+ background-clip: text !important;
74
+ }
75
+ .colorful {
76
+ opacity: 0;
77
+ animation-name: colorfulN;
78
+ }
79
+ .nocolor {
80
+ position: absolute;
81
+ top: 0;
82
+ background: var(${cssGlobalVars.clipBackground});
83
+ }
84
+ `,
85
+ )
86
+ class Breath extends GlobalStyle {
87
+ /**
88
+ * Strings or array of strings,
89
+ * if array, divided each element into chunks,
90
+ * otherwise split strings by whitespace.
91
+ */
92
+ @property()
93
+ text: string | string[];
94
+ /**
95
+ * Effect duration, ending in s or ms.
96
+ */
97
+ @property()
98
+ duration: string;
99
+
100
+ protected render() {
101
+ const texts = this.getTexts();
102
+ return [
103
+ texts.map(this.renderText),
104
+ htmlStyle(this.computeStyle(texts.length)),
105
+ ];
106
+ }
107
+
108
+ protected renderText(text: string) {
109
+ return html`<span class="rel">
110
+ <span class="nocolor">${text}</span>
111
+ <span class="colorful">${text}</span>
112
+ </span>`;
113
+ }
114
+
115
+ protected getTexts(): string[] {
116
+ return Array.isArray(this.text) ? this.text : (this.text || this.textContent).split(/\s+/).filter((x) => x);
117
+ }
118
+
119
+ protected computeStyle(len: number) {
120
+ const gap = 100 / 2 / len;
121
+ const duration = this.parseDuration() || len * 2 + 2;
122
+
123
+ return (
124
+ `.colorful{animation-duration:${duration}s;}`
125
+ + `@keyframes colorfulN{0%,${gap * 3}%{opacity:0;}${gap}%,${gap * 2}%{opacity:1;}}`
126
+ + (() => {
127
+ let style1 = "";
128
+ for (let number = 1; number <= len; number++) {
129
+ const delay = -duration / len * (len - number + 1);
130
+ const defaultNumber = ((number - 1) % 3) + 1;
131
+ style1 +=
132
+ `.rel:nth-child(${number}) .colorful{animation-delay:${delay}s;background:var(${cssScope}--${number},var(${cssScope}--${defaultNumber}));}`;
133
+ }
134
+ return style1;
135
+ })()
136
+ );
137
+ }
138
+
139
+ protected parseDuration() {
140
+ const { duration } = this;
141
+ if (duration) {
142
+ if (duration.endsWith("s")) {
143
+ return parseFloat(duration.slice(0, -1));
144
+ } else if (duration.endsWith("ms")) {
145
+ return parseFloat(duration.slice(0, -2)) / 1000;
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+ export default Breath;