@radishon/lumina 1.0.1 → 1.0.3

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,165 @@ 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
52
+
53
+ **重要配置**:需要在 `vite.config.js` 或 `vue.config.js` 中配置 `isCustomElement` 来禁用 Vue 对 Web Component 的解析:
54
+
55
+ #### Vite 项目
56
+
57
+ ```js
58
+ // vite.config.js
59
+ export default {
60
+ vue: {
61
+ template: {
62
+ compilerOptions: {
63
+ isCustomElement: tag => tag === 'lumina-loading'
64
+ }
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ #### Vue CLI 项目
71
+
72
+ ```js
73
+ // vue.config.js
74
+ module.exports = {
75
+ chainWebpack: config => {
76
+ config.module
77
+ .rule('vue')
78
+ .use('vue-loader')
79
+ .tap(options => ({
80
+ ...options,
81
+ compilerOptions: {
82
+ isCustomElement: tag => tag === 'lumina-loading'
83
+ }
84
+ }))
85
+ }
86
+ }
87
+ ```
88
+
89
+ **使用示例**:
44
90
 
45
91
  ```vue
46
92
  <template>
47
93
  <div class="loading-container">
48
- <Lumina />
94
+ <lumina-loading />
49
95
  </div>
50
96
  </template>
51
97
 
52
98
  <script setup>
53
- import { Lumina } from '@radishon/lumina'
99
+ import '@radishon/lumina'
54
100
  </script>
55
101
  ```
56
102
 
57
- ### Vue 2 使用示例
103
+ ### Vue 2
104
+
105
+ **重要配置**:需要在 `vue.config.js` 中配置 `isCustomElement`:
106
+
107
+ ```js
108
+ // vue.config.js
109
+ module.exports = {
110
+ chainWebpack: config => {
111
+ config.module
112
+ .rule('vue')
113
+ .use('vue-loader')
114
+ .tap(options => ({
115
+ ...options,
116
+ compilerOptions: {
117
+ isCustomElement: tag => tag === 'lumina-loading'
118
+ }
119
+ }))
120
+ }
121
+ }
122
+ ```
123
+
124
+ **使用示例**:
58
125
 
59
126
  ```vue
60
127
  <template>
61
128
  <div class="loading-container">
62
- <Lumina />
129
+ <lumina-loading />
63
130
  </div>
64
131
  </template>
65
132
 
66
133
  <script>
67
- import { Lumina } from '@radishon/lumina'
134
+ import '@radishon/lumina'
68
135
 
69
136
  export default {
70
- components: {
71
- Lumina
137
+ mounted() {
138
+ // Web Component 自动注册,无需额外操作
72
139
  }
73
140
  }
74
141
  </script>
75
142
  ```
76
143
 
144
+ ### Angular
145
+
146
+ ```typescript
147
+ // app.module.ts
148
+ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
149
+
150
+ @NgModule({
151
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
152
+ })
153
+ export class AppModule {}
154
+ ```
155
+
156
+ ```html
157
+ <!-- app.component.html -->
158
+ <lumina-loading></lumina-loading>
159
+ ```
160
+
161
+ ### Svelte
162
+
163
+ ```svelte
164
+ <script>
165
+ import '@radishon/lumina'
166
+ </script>
167
+
168
+ <lumina-loading />
169
+ ```
170
+
77
171
  ### 自定义序列类型
78
172
 
79
- ```tsx
80
- import { Lumina } from 'lumina';
173
+ ```html
174
+ <!-- 使用菱形脉冲效果 -->
175
+ <lumina-loading type="diamond"></lumina-loading>
81
176
 
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
- }
177
+ <!-- 使用月相变化效果,调整动画速度 -->
178
+ <lumina-loading type="moon" speed="300"></lumina-loading>
179
+
180
+ <!-- 使用赛博朋克风格 -->
181
+ <lumina-loading type="braille" speed="100"></lumina-loading>
182
+ ```
183
+
184
+ ### JavaScript 动态控制
185
+
186
+ ```javascript
187
+ const el = document.querySelector('lumina-loading');
188
+ el.type = 'star';
189
+ el.speed = 200;
96
190
  ```
97
191
 
98
192
  ## Props API
@@ -101,7 +195,6 @@ function App() {
101
195
  |------|------|--------|------|
102
196
  | `type` | `SequenceKey` | `'claude'` | 动画序列类型,见下方可用序列列表 |
103
197
  | `speed` | `number` | `180` | 动画帧切换速度(毫秒) |
104
- | `showBar` | `boolean` | `true` | 是否显示进度条(目前未实现) |
105
198
 
106
199
  ## 可用的序列类型
107
200
 
@@ -116,7 +209,7 @@ Lumina 提供了 16 种精心设计的动画序列:
116
209
  | `flower` | 开花绽放 | 花朵绽放动画 | 粉色 `#ffadd2` |
117
210
  | `star` | 星辰回环 | 星星旋转变化 | 白色 `#ffffff` |
118
211
  | `snow` | 雪花晶格 | 雪花飘落效果 | 冰蓝 `#e6f7ff` |
119
- | `spiral` | 螰旋回声 | 螰旋圆环变化 | 金黄色 `#fadb14` |
212
+ | `spiral` | 螺旋回声 | 螺旋圆环变化 | 金黄色 `#fadb14` |
120
213
  | `braille` | 布莱叶码 | 赛博朋克风格的布莱叶点码动画 | 荧光绿 `#00ff00` |
121
214
  | `cypher` | 密码矩阵 | 赛博朋克几何方块变换 | 霓虹蓝 `#00d8ff` |
122
215
  | `moon` | 月相变化 | 自然风格的月相周期动画 | 月光白 `#fffae6` |
@@ -165,7 +258,7 @@ npm link
165
258
  然后在目标项目中:
166
259
 
167
260
  ```bash
168
- npm link lumina
261
+ npm link @radishon/lumina
169
262
  ```
170
263
 
171
264
  ## 许可证
@@ -174,4 +267,4 @@ MIT
174
267
 
175
268
  ## 贡献
176
269
 
177
- 欢迎提交 Issue 和 Pull Request!
270
+ 欢迎提交 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.3",
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
  }