@radishon/lumina 1.0.1 → 1.0.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 CHANGED
@@ -1,10 +1,12 @@
1
1
  # Lumina
2
2
 
3
- 一个优雅的 React 动画加载指示器组件,提供多种预设动画序列,为你的应用增添独特的视觉体验。
3
+ 一个优雅的动画加载指示器 **Web Component**,提供多种预设动画序列,为你的应用增添独特的视觉体验。**适用于所有前端框架**。
4
4
 
5
5
  ## 简介
6
6
 
7
- Lumina 是一个轻量级的 React Loading 组件,通过精心设计的 Unicode 字符序列和颜色配置,呈现出流畅的动画效果。无论是科技感的赛博朋克风格,还是自然的月相变化,都能为你的应用加载状态提供独特的视觉表达。
7
+ Lumina 是一个轻量级的 Loading 组件,通过精心设计的 Unicode 字符序列和颜色配置,呈现出流畅的动画效果。无论是科技感的赛博朋克风格,还是自然的月相变化,都能为你的应用加载状态提供独特的视觉表达。
8
+
9
+ **框架无关** - 可在 React、Vue、Angular、Svelte 或任何 HTML 页面中使用。
8
10
 
9
11
  ## 安装
10
12
 
@@ -26,73 +28,106 @@ pnpm add @radishon/lumina
26
28
 
27
29
  ## 使用示例
28
30
 
29
- ### 基本用法 (React)
31
+ ### 基本用法 (所有框架)
32
+
33
+ ```html
34
+ <lumina-loading></lumina-loading>
35
+ ```
36
+
37
+ ### React
30
38
 
31
39
  ```tsx
32
- import { Lumina } from '@radishon/lumina';
40
+ import '@radishon/lumina';
33
41
 
34
42
  function App() {
35
43
  return (
36
44
  <div className="loading-container">
37
- <Lumina />
45
+ <lumina-loading />
38
46
  </div>
39
47
  );
40
48
  }
41
49
  ```
42
50
 
43
- ### Vue 3 使用示例
51
+ ### Vue 3
44
52
 
45
53
  ```vue
46
54
  <template>
47
55
  <div class="loading-container">
48
- <Lumina />
56
+ <lumina-loading />
49
57
  </div>
50
58
  </template>
51
59
 
52
60
  <script setup>
53
- import { Lumina } from '@radishon/lumina'
61
+ import '@radishon/lumina'
54
62
  </script>
55
63
  ```
56
64
 
57
- ### Vue 2 使用示例
65
+ ### Vue 2
58
66
 
59
67
  ```vue
60
68
  <template>
61
69
  <div class="loading-container">
62
- <Lumina />
70
+ <lumina-loading />
63
71
  </div>
64
72
  </template>
65
73
 
66
74
  <script>
67
- import { Lumina } from '@radishon/lumina'
75
+ import '@radishon/lumina'
68
76
 
69
77
  export default {
70
- components: {
71
- Lumina
78
+ mounted() {
79
+ // Web Component 自动注册,无需额外操作
72
80
  }
73
81
  }
74
82
  </script>
75
83
  ```
76
84
 
85
+ ### Angular
86
+
87
+ ```typescript
88
+ // app.module.ts
89
+ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
90
+
91
+ @NgModule({
92
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
93
+ })
94
+ export class AppModule {}
95
+ ```
96
+
97
+ ```html
98
+ <!-- app.component.html -->
99
+ <lumina-loading></lumina-loading>
100
+ ```
101
+
102
+ ### Svelte
103
+
104
+ ```svelte
105
+ <script>
106
+ import '@radishon/lumina'
107
+ </script>
108
+
109
+ <lumina-loading />
110
+ ```
111
+
77
112
  ### 自定义序列类型
78
113
 
79
- ```tsx
80
- import { Lumina } from 'lumina';
114
+ ```html
115
+ <!-- 使用菱形脉冲效果 -->
116
+ <lumina-loading type="diamond"></lumina-loading>
81
117
 
82
- function App() {
83
- return (
84
- <div>
85
- {/* 使用菱形脉冲效果 */}
86
- <Lumina type="diamond" />
87
-
88
- {/* 使用月相变化效果,调整动画速度 */}
89
- <Lumina type="moon" speed={300} />
90
-
91
- {/* 使用赛博朋克风格 */}
92
- <Lumina type="braille" speed={100} />
93
- </div>
94
- );
95
- }
118
+ <!-- 使用月相变化效果,调整动画速度 -->
119
+ <lumina-loading type="moon" speed="300"></lumina-loading>
120
+
121
+ <!-- 使用赛博朋克风格 -->
122
+ <lumina-loading type="braille" speed="100"></lumina-loading>
123
+ ```
124
+
125
+ ### JavaScript 动态控制
126
+
127
+ ```javascript
128
+ const el = document.querySelector('lumina-loading');
129
+ el.type = 'star';
130
+ el.speed = 200;
96
131
  ```
97
132
 
98
133
  ## Props API
@@ -101,7 +136,6 @@ function App() {
101
136
  |------|------|--------|------|
102
137
  | `type` | `SequenceKey` | `'claude'` | 动画序列类型,见下方可用序列列表 |
103
138
  | `speed` | `number` | `180` | 动画帧切换速度(毫秒) |
104
- | `showBar` | `boolean` | `true` | 是否显示进度条(目前未实现) |
105
139
 
106
140
  ## 可用的序列类型
107
141
 
@@ -116,7 +150,7 @@ Lumina 提供了 16 种精心设计的动画序列:
116
150
  | `flower` | 开花绽放 | 花朵绽放动画 | 粉色 `#ffadd2` |
117
151
  | `star` | 星辰回环 | 星星旋转变化 | 白色 `#ffffff` |
118
152
  | `snow` | 雪花晶格 | 雪花飘落效果 | 冰蓝 `#e6f7ff` |
119
- | `spiral` | 螰旋回声 | 螰旋圆环变化 | 金黄色 `#fadb14` |
153
+ | `spiral` | 螺旋回声 | 螺旋圆环变化 | 金黄色 `#fadb14` |
120
154
  | `braille` | 布莱叶码 | 赛博朋克风格的布莱叶点码动画 | 荧光绿 `#00ff00` |
121
155
  | `cypher` | 密码矩阵 | 赛博朋克几何方块变换 | 霓虹蓝 `#00d8ff` |
122
156
  | `moon` | 月相变化 | 自然风格的月相周期动画 | 月光白 `#fffae6` |
@@ -165,7 +199,7 @@ npm link
165
199
  然后在目标项目中:
166
200
 
167
201
  ```bash
168
- npm link lumina
202
+ npm link @radishon/lumina
169
203
  ```
170
204
 
171
205
  ## 许可证
@@ -174,4 +208,4 @@ MIT
174
208
 
175
209
  ## 贡献
176
210
 
177
- 欢迎提交 Issue 和 Pull Request!
211
+ 欢迎提交 Issue 和 Pull Request!
package/dist/index.d.mts CHANGED
@@ -1,81 +1,25 @@
1
- import React from 'react';
2
-
3
- declare const SEQUENCES: {
4
- claude: {
5
- name: string;
6
- chars: string[];
7
- color: string;
8
- };
9
- diamond: {
10
- name: string;
11
- chars: string[];
12
- color: string;
13
- };
14
- circle: {
15
- name: string;
16
- chars: string[];
17
- color: string;
18
- };
19
- step: {
20
- name: string;
21
- chars: string[];
22
- color: string;
23
- };
24
- flower: {
25
- name: string;
26
- chars: string[];
27
- color: string;
28
- };
29
- star: {
30
- name: string;
31
- chars: string[];
32
- color: string;
33
- };
34
- snow: {
35
- name: string;
36
- chars: string[];
37
- color: string;
38
- };
39
- spiral: {
40
- name: string;
41
- chars: string[];
42
- color: string;
43
- };
44
- braille: {
45
- chars: string[];
46
- color: string;
47
- };
48
- cypher: {
49
- chars: string[];
50
- color: string;
51
- };
52
- moon: {
53
- chars: string[];
54
- color: string;
55
- };
56
- wave: {
57
- chars: string[];
58
- color: string;
59
- };
60
- compass: {
61
- chars: string[];
62
- color: string;
63
- };
64
- pixel: {
65
- chars: string[];
66
- color: string;
67
- };
68
- clock: {
69
- chars: string[];
70
- color: string;
71
- };
72
- };
1
+ interface SequenceConfig {
2
+ name: string;
3
+ chars: string[];
4
+ color: string;
5
+ }
6
+ declare const SEQUENCES: Record<string, SequenceConfig>;
73
7
  type SequenceKey = keyof typeof SEQUENCES;
74
- interface LuminaProps {
75
- type?: SequenceKey;
76
- speed?: number;
77
- showBar?: boolean;
8
+ declare class LuminaElement extends HTMLElement {
9
+ private _index;
10
+ private _timer;
11
+ private _div;
12
+ static get observedAttributes(): string[];
13
+ constructor();
14
+ connectedCallback(): void;
15
+ disconnectedCallback(): void;
16
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
17
+ get type(): SequenceKey;
18
+ set type(value: SequenceKey);
19
+ get speed(): number;
20
+ set speed(value: number);
21
+ private render;
22
+ private startAnimation;
78
23
  }
79
- declare const Lumina: React.FC<LuminaProps>;
80
24
 
81
- export { Lumina, type SequenceKey };
25
+ export { LuminaElement as Lumina, LuminaElement, type SequenceKey };
package/dist/index.d.ts CHANGED
@@ -1,81 +1,25 @@
1
- import React from 'react';
2
-
3
- declare const SEQUENCES: {
4
- claude: {
5
- name: string;
6
- chars: string[];
7
- color: string;
8
- };
9
- diamond: {
10
- name: string;
11
- chars: string[];
12
- color: string;
13
- };
14
- circle: {
15
- name: string;
16
- chars: string[];
17
- color: string;
18
- };
19
- step: {
20
- name: string;
21
- chars: string[];
22
- color: string;
23
- };
24
- flower: {
25
- name: string;
26
- chars: string[];
27
- color: string;
28
- };
29
- star: {
30
- name: string;
31
- chars: string[];
32
- color: string;
33
- };
34
- snow: {
35
- name: string;
36
- chars: string[];
37
- color: string;
38
- };
39
- spiral: {
40
- name: string;
41
- chars: string[];
42
- color: string;
43
- };
44
- braille: {
45
- chars: string[];
46
- color: string;
47
- };
48
- cypher: {
49
- chars: string[];
50
- color: string;
51
- };
52
- moon: {
53
- chars: string[];
54
- color: string;
55
- };
56
- wave: {
57
- chars: string[];
58
- color: string;
59
- };
60
- compass: {
61
- chars: string[];
62
- color: string;
63
- };
64
- pixel: {
65
- chars: string[];
66
- color: string;
67
- };
68
- clock: {
69
- chars: string[];
70
- color: string;
71
- };
72
- };
1
+ interface SequenceConfig {
2
+ name: string;
3
+ chars: string[];
4
+ color: string;
5
+ }
6
+ declare const SEQUENCES: Record<string, SequenceConfig>;
73
7
  type SequenceKey = keyof typeof SEQUENCES;
74
- interface LuminaProps {
75
- type?: SequenceKey;
76
- speed?: number;
77
- showBar?: boolean;
8
+ declare class LuminaElement extends HTMLElement {
9
+ private _index;
10
+ private _timer;
11
+ private _div;
12
+ static get observedAttributes(): string[];
13
+ constructor();
14
+ connectedCallback(): void;
15
+ disconnectedCallback(): void;
16
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
17
+ get type(): SequenceKey;
18
+ set type(value: SequenceKey);
19
+ get speed(): number;
20
+ set speed(value: number);
21
+ private render;
22
+ private startAnimation;
78
23
  }
79
- declare const Lumina: React.FC<LuminaProps>;
80
24
 
81
- export { Lumina, type SequenceKey };
25
+ export { LuminaElement as Lumina, LuminaElement, type SequenceKey };
package/dist/index.js CHANGED
@@ -20,13 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- Lumina: () => Lumina_default
23
+ Lumina: () => Lumina_default,
24
+ LuminaElement: () => Lumina_default
24
25
  });
25
26
  module.exports = __toCommonJS(index_exports);
26
27
 
27
- // src/Lumina.tsx
28
- var import_react = require("react");
29
- var import_jsx_runtime = require("react/jsx-runtime");
28
+ // src/Lumina.ts
30
29
  var SEQUENCES = {
31
30
  claude: {
32
31
  name: "CLAUDE \u8F68\u8FF9",
@@ -68,71 +67,129 @@ var SEQUENCES = {
68
67
  chars: ["\u25C9", "\u25CE", "\u25CB", "\u25CC", "\u25CD", "\u25CF", "\u25D0", "\u25D1"],
69
68
  color: "#fadb14"
70
69
  },
71
- // 1. Cyberpunk
72
70
  braille: {
71
+ name: "\u5E03\u83B1\u53F6\u7801",
73
72
  chars: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
74
73
  color: "#00ff00"
75
74
  },
76
- cypher: { chars: ["\u259E", "\u259A", "\u259C", "\u2599", "\u259F", "\u259B"], color: "#00d8ff" },
77
- // 2. Nature
75
+ cypher: {
76
+ name: "\u5BC6\u7801\u77E9\u9635",
77
+ chars: ["\u259E", "\u259A", "\u259C", "\u2599", "\u259F", "\u259B"],
78
+ color: "#00d8ff"
79
+ },
78
80
  moon: {
81
+ name: "\u6708\u76F8\u53D8\u5316",
79
82
  chars: ["\u{1F311}", "\u{1F312}", "\u{1F313}", "\u{1F314}", "\u{1F315}", "\u{1F316}", "\u{1F317}", "\u{1F318}"],
80
83
  color: "#fffae6"
81
84
  },
82
- wave: { chars: ["_", "\u23BD", "\u23BC", "\u23BB", "\u23BA", "\u23BB", "\u23BC", "\u23BD"], color: "#ff4d4f" },
83
- // 3. Logic
85
+ wave: {
86
+ name: "\u6CE2\u6D6A\u8D77\u4F0F",
87
+ chars: ["_", "\u23BD", "\u23BC", "\u23BB", "\u23BA", "\u23BB", "\u23BC", "\u23BD"],
88
+ color: "#ff4d4f"
89
+ },
84
90
  compass: {
91
+ name: "\u65B9\u5411\u7F57\u76D8",
85
92
  chars: ["\u2191", "\u2197", "\u2192", "\u2198", "\u2193", "\u2199", "\u2190", "\u2196"],
86
93
  color: "#ff4500"
87
94
  },
88
- // 4. Retro
89
- pixel: { chars: ["\u25A3", "\u25A4", "\u25A5", "\u25A6", "\u25A7", "\u25A8", "\u25A9"], color: "#722ed1" },
95
+ pixel: {
96
+ name: "\u50CF\u7D20\u65B9\u5757",
97
+ chars: ["\u25A3", "\u25A4", "\u25A5", "\u25A6", "\u25A7", "\u25A8", "\u25A9"],
98
+ color: "#722ed1"
99
+ },
90
100
  clock: {
91
- chars: [
92
- "\u{1F550}",
93
- "\u{1F551}",
94
- "\u{1F552}",
95
- "\u{1F553}",
96
- "\u{1F554}",
97
- "\u{1F555}",
98
- "\u{1F556}",
99
- "\u{1F557}",
100
- "\u{1F558}",
101
- "\u{1F559}",
102
- "\u{1F55A}",
103
- "\u{1F55B}"
104
- ],
101
+ name: "\u65F6\u949F\u6307\u9488",
102
+ chars: ["\u{1F550}", "\u{1F551}", "\u{1F552}", "\u{1F553}", "\u{1F554}", "\u{1F555}", "\u{1F556}", "\u{1F557}", "\u{1F558}", "\u{1F559}", "\u{1F55A}", "\u{1F55B}"],
105
103
  color: "#ffbb96"
106
104
  }
107
105
  };
108
- var Lumina = ({
109
- type = "claude",
110
- speed = 180,
111
- showBar = true
112
- }) => {
113
- const [index, setIndex] = (0, import_react.useState)(0);
114
- const config = SEQUENCES[type];
115
- (0, import_react.useEffect)(() => {
116
- const timer = setInterval(() => {
117
- setIndex((prevIndex) => (prevIndex + 1) % config.chars.length);
118
- }, speed);
119
- return () => clearInterval(timer);
120
- }, [config.chars.length, speed]);
121
- const glowStyle = {
122
- color: config.color,
123
- textShadow: `0 0 20px ${config.color}66`,
124
- fontSize: "42px",
125
- height: "60px",
126
- display: "flex",
127
- alignItems: "center",
128
- justifyContent: "center",
129
- transition: "all 0.2s ease",
130
- fontFamily: "monospace"
131
- };
132
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: glowStyle, children: config.chars[index] });
106
+ var LuminaElement = class extends HTMLElement {
107
+ constructor() {
108
+ super();
109
+ this._index = 0;
110
+ this._timer = null;
111
+ this._div = null;
112
+ this.attachShadow({ mode: "open" });
113
+ }
114
+ static get observedAttributes() {
115
+ return ["type", "speed"];
116
+ }
117
+ connectedCallback() {
118
+ this.render();
119
+ this.startAnimation();
120
+ }
121
+ disconnectedCallback() {
122
+ if (this._timer) {
123
+ clearInterval(this._timer);
124
+ }
125
+ }
126
+ attributeChangedCallback(name, oldValue, newValue) {
127
+ if (oldValue !== newValue) {
128
+ if (name === "speed" && this._timer) {
129
+ this.startAnimation();
130
+ }
131
+ if (name === "type") {
132
+ this.render();
133
+ this.startAnimation();
134
+ }
135
+ }
136
+ }
137
+ get type() {
138
+ return this.getAttribute("type") || "claude";
139
+ }
140
+ set type(value) {
141
+ this.setAttribute("type", value);
142
+ }
143
+ get speed() {
144
+ const speed = this.getAttribute("speed");
145
+ return speed !== null ? parseInt(speed, 10) : 180;
146
+ }
147
+ set speed(value) {
148
+ this.setAttribute("speed", String(value));
149
+ }
150
+ render() {
151
+ const config = SEQUENCES[this.type] || SEQUENCES["claude"];
152
+ const currentChar = config.chars[this._index] || config.chars[0];
153
+ this.shadowRoot.innerHTML = `
154
+ <style>
155
+ :host {
156
+ display: inline-block;
157
+ }
158
+ .container {
159
+ color: ${config.color};
160
+ text-shadow: 0 0 20px ${config.color}66;
161
+ font-size: 42px;
162
+ height: 60px;
163
+ display: flex;
164
+ align-items: center;
165
+ justify-content: center;
166
+ transition: all 0.2s ease;
167
+ font-family: monospace;
168
+ }
169
+ </style>
170
+ <div class="container">${currentChar}</div>
171
+ `;
172
+ this._div = this.shadowRoot.querySelector(".container");
173
+ }
174
+ startAnimation() {
175
+ if (this._timer) {
176
+ clearInterval(this._timer);
177
+ }
178
+ const config = SEQUENCES[this.type] || SEQUENCES["claude"];
179
+ this._timer = setInterval(() => {
180
+ this._index = (this._index + 1) % config.chars.length;
181
+ if (this._div) {
182
+ this._div.textContent = config.chars[this._index];
183
+ }
184
+ }, this.speed);
185
+ }
133
186
  };
134
- var Lumina_default = Lumina;
187
+ if (typeof customElements !== "undefined" && !customElements.get("lumina-loading")) {
188
+ customElements.define("lumina-loading", LuminaElement);
189
+ }
190
+ var Lumina_default = LuminaElement;
135
191
  // Annotate the CommonJS export names for ESM import in node:
136
192
  0 && (module.exports = {
137
- Lumina
193
+ Lumina,
194
+ LuminaElement
138
195
  });
package/dist/index.mjs CHANGED
@@ -1,6 +1,4 @@
1
- // src/Lumina.tsx
2
- import { useState, useEffect } from "react";
3
- import { jsx } from "react/jsx-runtime";
1
+ // src/Lumina.ts
4
2
  var SEQUENCES = {
5
3
  claude: {
6
4
  name: "CLAUDE \u8F68\u8FF9",
@@ -42,70 +40,128 @@ var SEQUENCES = {
42
40
  chars: ["\u25C9", "\u25CE", "\u25CB", "\u25CC", "\u25CD", "\u25CF", "\u25D0", "\u25D1"],
43
41
  color: "#fadb14"
44
42
  },
45
- // 1. Cyberpunk
46
43
  braille: {
44
+ name: "\u5E03\u83B1\u53F6\u7801",
47
45
  chars: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
48
46
  color: "#00ff00"
49
47
  },
50
- cypher: { chars: ["\u259E", "\u259A", "\u259C", "\u2599", "\u259F", "\u259B"], color: "#00d8ff" },
51
- // 2. Nature
48
+ cypher: {
49
+ name: "\u5BC6\u7801\u77E9\u9635",
50
+ chars: ["\u259E", "\u259A", "\u259C", "\u2599", "\u259F", "\u259B"],
51
+ color: "#00d8ff"
52
+ },
52
53
  moon: {
54
+ name: "\u6708\u76F8\u53D8\u5316",
53
55
  chars: ["\u{1F311}", "\u{1F312}", "\u{1F313}", "\u{1F314}", "\u{1F315}", "\u{1F316}", "\u{1F317}", "\u{1F318}"],
54
56
  color: "#fffae6"
55
57
  },
56
- wave: { chars: ["_", "\u23BD", "\u23BC", "\u23BB", "\u23BA", "\u23BB", "\u23BC", "\u23BD"], color: "#ff4d4f" },
57
- // 3. Logic
58
+ wave: {
59
+ name: "\u6CE2\u6D6A\u8D77\u4F0F",
60
+ chars: ["_", "\u23BD", "\u23BC", "\u23BB", "\u23BA", "\u23BB", "\u23BC", "\u23BD"],
61
+ color: "#ff4d4f"
62
+ },
58
63
  compass: {
64
+ name: "\u65B9\u5411\u7F57\u76D8",
59
65
  chars: ["\u2191", "\u2197", "\u2192", "\u2198", "\u2193", "\u2199", "\u2190", "\u2196"],
60
66
  color: "#ff4500"
61
67
  },
62
- // 4. Retro
63
- pixel: { chars: ["\u25A3", "\u25A4", "\u25A5", "\u25A6", "\u25A7", "\u25A8", "\u25A9"], color: "#722ed1" },
68
+ pixel: {
69
+ name: "\u50CF\u7D20\u65B9\u5757",
70
+ chars: ["\u25A3", "\u25A4", "\u25A5", "\u25A6", "\u25A7", "\u25A8", "\u25A9"],
71
+ color: "#722ed1"
72
+ },
64
73
  clock: {
65
- chars: [
66
- "\u{1F550}",
67
- "\u{1F551}",
68
- "\u{1F552}",
69
- "\u{1F553}",
70
- "\u{1F554}",
71
- "\u{1F555}",
72
- "\u{1F556}",
73
- "\u{1F557}",
74
- "\u{1F558}",
75
- "\u{1F559}",
76
- "\u{1F55A}",
77
- "\u{1F55B}"
78
- ],
74
+ name: "\u65F6\u949F\u6307\u9488",
75
+ chars: ["\u{1F550}", "\u{1F551}", "\u{1F552}", "\u{1F553}", "\u{1F554}", "\u{1F555}", "\u{1F556}", "\u{1F557}", "\u{1F558}", "\u{1F559}", "\u{1F55A}", "\u{1F55B}"],
79
76
  color: "#ffbb96"
80
77
  }
81
78
  };
82
- var Lumina = ({
83
- type = "claude",
84
- speed = 180,
85
- showBar = true
86
- }) => {
87
- const [index, setIndex] = useState(0);
88
- const config = SEQUENCES[type];
89
- useEffect(() => {
90
- const timer = setInterval(() => {
91
- setIndex((prevIndex) => (prevIndex + 1) % config.chars.length);
92
- }, speed);
93
- return () => clearInterval(timer);
94
- }, [config.chars.length, speed]);
95
- const glowStyle = {
96
- color: config.color,
97
- textShadow: `0 0 20px ${config.color}66`,
98
- fontSize: "42px",
99
- height: "60px",
100
- display: "flex",
101
- alignItems: "center",
102
- justifyContent: "center",
103
- transition: "all 0.2s ease",
104
- fontFamily: "monospace"
105
- };
106
- return /* @__PURE__ */ jsx("div", { style: glowStyle, children: config.chars[index] });
79
+ var LuminaElement = class extends HTMLElement {
80
+ constructor() {
81
+ super();
82
+ this._index = 0;
83
+ this._timer = null;
84
+ this._div = null;
85
+ this.attachShadow({ mode: "open" });
86
+ }
87
+ static get observedAttributes() {
88
+ return ["type", "speed"];
89
+ }
90
+ connectedCallback() {
91
+ this.render();
92
+ this.startAnimation();
93
+ }
94
+ disconnectedCallback() {
95
+ if (this._timer) {
96
+ clearInterval(this._timer);
97
+ }
98
+ }
99
+ attributeChangedCallback(name, oldValue, newValue) {
100
+ if (oldValue !== newValue) {
101
+ if (name === "speed" && this._timer) {
102
+ this.startAnimation();
103
+ }
104
+ if (name === "type") {
105
+ this.render();
106
+ this.startAnimation();
107
+ }
108
+ }
109
+ }
110
+ get type() {
111
+ return this.getAttribute("type") || "claude";
112
+ }
113
+ set type(value) {
114
+ this.setAttribute("type", value);
115
+ }
116
+ get speed() {
117
+ const speed = this.getAttribute("speed");
118
+ return speed !== null ? parseInt(speed, 10) : 180;
119
+ }
120
+ set speed(value) {
121
+ this.setAttribute("speed", String(value));
122
+ }
123
+ render() {
124
+ const config = SEQUENCES[this.type] || SEQUENCES["claude"];
125
+ const currentChar = config.chars[this._index] || config.chars[0];
126
+ this.shadowRoot.innerHTML = `
127
+ <style>
128
+ :host {
129
+ display: inline-block;
130
+ }
131
+ .container {
132
+ color: ${config.color};
133
+ text-shadow: 0 0 20px ${config.color}66;
134
+ font-size: 42px;
135
+ height: 60px;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ transition: all 0.2s ease;
140
+ font-family: monospace;
141
+ }
142
+ </style>
143
+ <div class="container">${currentChar}</div>
144
+ `;
145
+ this._div = this.shadowRoot.querySelector(".container");
146
+ }
147
+ startAnimation() {
148
+ if (this._timer) {
149
+ clearInterval(this._timer);
150
+ }
151
+ const config = SEQUENCES[this.type] || SEQUENCES["claude"];
152
+ this._timer = setInterval(() => {
153
+ this._index = (this._index + 1) % config.chars.length;
154
+ if (this._div) {
155
+ this._div.textContent = config.chars[this._index];
156
+ }
157
+ }, this.speed);
158
+ }
107
159
  };
108
- var Lumina_default = Lumina;
160
+ if (typeof customElements !== "undefined" && !customElements.get("lumina-loading")) {
161
+ customElements.define("lumina-loading", LuminaElement);
162
+ }
163
+ var Lumina_default = LuminaElement;
109
164
  export {
110
- Lumina_default as Lumina
165
+ Lumina_default as Lumina,
166
+ Lumina_default as LuminaElement
111
167
  };
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@radishon/lumina",
3
- "version": "1.0.1",
4
- "description": "A beautiful animated loading indicator component for React with multiple preset sequences",
3
+ "version": "1.0.2",
4
+ "description": "A beautiful animated loading indicator web component for all frameworks",
5
5
  "main": "dist/index.js",
6
- "module": "dist/index.esm.js",
6
+ "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "files": [
9
9
  "dist"
@@ -14,28 +14,23 @@
14
14
  "prepublishOnly": "npm run build"
15
15
  },
16
16
  "keywords": [
17
- "react",
18
17
  "loading",
19
18
  "spinner",
20
19
  "animation",
21
20
  "lumina",
22
- "component"
21
+ "web-component",
22
+ "react",
23
+ "vue",
24
+ "angular",
25
+ "svelte"
23
26
  ],
24
27
  "author": "",
25
28
  "license": "MIT",
26
29
  "publishConfig": {
27
30
  "access": "public"
28
31
  },
29
- "peerDependencies": {
30
- "react": ">=16.8.0",
31
- "react-dom": ">=16.8.0",
32
- "vue": ">=2.0.0 || >=3.0.0"
33
- },
32
+ "peerDependencies": {},
34
33
  "devDependencies": {
35
- "@types/react": "^18.0.0",
36
- "@types/react-dom": "^18.0.0",
37
- "react": "^18.0.0",
38
- "react-dom": "^18.0.0",
39
34
  "tsup": "^8.0.0",
40
35
  "typescript": "^5.0.0"
41
36
  }