@ahriknow/lux 0.0.1

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/README_zh-CN.md +127 -0
  4. package/dist/components/lux-button/index.iife.min.js +292 -0
  5. package/dist/components/lux-button/index.min.js +292 -0
  6. package/dist/components/lux-code/index.iife.min.js +290 -0
  7. package/dist/components/lux-code/index.min.js +290 -0
  8. package/dist/components/lux-dropdown/index.iife.min.js +162 -0
  9. package/dist/components/lux-dropdown/index.min.js +162 -0
  10. package/dist/components/lux-example/index.iife.min.js +88 -0
  11. package/dist/components/lux-example/index.min.js +88 -0
  12. package/dist/components/lux-icon/index.iife.min.js +22 -0
  13. package/dist/components/lux-icon/index.min.js +22 -0
  14. package/dist/components/lux-input/index.iife.min.js +238 -0
  15. package/dist/components/lux-input/index.min.js +238 -0
  16. package/dist/components/lux-layout/index.iife.min.js +90 -0
  17. package/dist/components/lux-layout/index.min.js +90 -0
  18. package/dist/components/lux-menu/index.iife.min.js +193 -0
  19. package/dist/components/lux-menu/index.min.js +193 -0
  20. package/dist/components/lux-scroll/index.iife.min.js +137 -0
  21. package/dist/components/lux-scroll/index.min.js +137 -0
  22. package/dist/components/lux-switch/index.iife.min.js +116 -0
  23. package/dist/components/lux-switch/index.min.js +116 -0
  24. package/dist/components/lux-table/index.iife.min.js +67 -0
  25. package/dist/components/lux-table/index.min.js +67 -0
  26. package/dist/lux.core.min.js +1 -0
  27. package/dist/lux.i18n.min.js +1 -0
  28. package/dist/lux.iife.js +1822 -0
  29. package/dist/lux.iife.js.map +1 -0
  30. package/dist/lux.iife.min.js +1 -0
  31. package/dist/lux.js +1792 -0
  32. package/dist/lux.js.map +1 -0
  33. package/dist/lux.min.js +1 -0
  34. package/dist/lux.router.min.js +1 -0
  35. package/dist/lux.template.min.js +1 -0
  36. package/dist/lux.theme.min.js +1 -0
  37. package/dist/themes/dark.css +130 -0
  38. package/dist/themes/light.css +128 -0
  39. package/package.json +64 -0
  40. package/src/components/lux-button/index.js +319 -0
  41. package/src/components/lux-code/index.js +382 -0
  42. package/src/components/lux-dropdown/index.js +256 -0
  43. package/src/components/lux-example/index.js +117 -0
  44. package/src/components/lux-icon/index.js +180 -0
  45. package/src/components/lux-input/index.js +363 -0
  46. package/src/components/lux-layout/index.js +222 -0
  47. package/src/components/lux-menu/index.js +283 -0
  48. package/src/components/lux-scroll/index.js +349 -0
  49. package/src/components/lux-switch/index.js +203 -0
  50. package/src/components/lux-table/index.js +105 -0
  51. package/src/core.js +7 -0
  52. package/src/element.js +477 -0
  53. package/src/i18n/format.js +108 -0
  54. package/src/i18n/index.js +102 -0
  55. package/src/i18n/locale.js +26 -0
  56. package/src/index.js +22 -0
  57. package/src/router.js +330 -0
  58. package/src/template.js +402 -0
  59. package/src/theme/color.js +148 -0
  60. package/src/theme/create.js +97 -0
  61. package/src/theme/index.js +2 -0
  62. package/src/theme/tokens.js +128 -0
  63. package/src/themes/dark.css +130 -0
  64. package/src/themes/light.css +128 -0
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@ahriknow/lux",
3
+ "version": "0.0.1",
4
+ "description": "Lightweight Web Components framework with reactive properties, template engine, router, and i18n",
5
+ "type": "module",
6
+ "main": "dist/lux.iife.js",
7
+ "module": "dist/lux.js",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/lux.js",
11
+ "require": "./dist/lux.iife.js",
12
+ "default": "./dist/lux.js"
13
+ },
14
+ "./template": {
15
+ "import": "./dist/lux.template.js",
16
+ "default": "./dist/lux.template.js"
17
+ },
18
+ "./element": "./src/element.js",
19
+ "./router": "./src/router.js",
20
+ "./code": "./src/components/lux-code/index.js"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "src",
25
+ "README.md",
26
+ "README_zh-CN.md",
27
+ "LICENSE"
28
+ ],
29
+ "scripts": {
30
+ "build": "rollup -c && node -e \"const fs=require('fs'),p=require('path');['docs/themes','dist/themes'].forEach(d=>{fs.mkdirSync(d,{recursive:true});fs.readdirSync('src/themes').filter(f=>f.endsWith('.css')).forEach(f=>fs.copyFileSync(p.join('src/themes',f),p.join(d,f)))})\"",
31
+ "dev": "npx serve ./docs -l 6001",
32
+ "format": "prettier --write \"src/**/*.js\" \"docs/**/*.js\"",
33
+ "format:check": "prettier --check \"src/**/*.js\" \"docs/**/*.js\""
34
+ },
35
+ "keywords": [
36
+ "web-components",
37
+ "shadow-dom",
38
+ "router",
39
+ "template",
40
+ "components",
41
+ "ui",
42
+ "library",
43
+ "framework",
44
+ "ui library"
45
+ ],
46
+ "author": "ahriknow <ahriknow@ahriknow.com>",
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/ahriknow/lux.git"
51
+ },
52
+ "bugs": {
53
+ "url": "https://github.com/ahriknow/lux/issues"
54
+ },
55
+ "homepage": "https://github.com/ahriknow/lux#readme",
56
+ "devDependencies": {
57
+ "@rollup/plugin-terser": "^1.0.0",
58
+ "prettier": "^3.9.6",
59
+ "rollup": "^4.62.2"
60
+ },
61
+ "engines": {
62
+ "node": ">=18.0.0"
63
+ }
64
+ }
@@ -0,0 +1,319 @@
1
+ /**
2
+ * lux-button — Button component.
3
+ *
4
+ * Props:
5
+ * variant — primary / secondary / success / warning / error / info (default: primary)
6
+ * outline — outline style (boolean)
7
+ * ghost — ghost style (boolean)
8
+ * size — sm / md / lg (default: md)
9
+ * shape — circle / square (default: none)
10
+ * icon — icon name from lux-icon registry
11
+ * disabled — disable interaction
12
+ * loading — show loading spinner
13
+ * block — full width
14
+ */
15
+
16
+ import { html, css, LuxElement, registerComponent } from '../../index.js';
17
+ import '../lux-icon/index.js';
18
+
19
+ const styles = css`
20
+ :host {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ cursor: pointer;
25
+ vertical-align: middle;
26
+ user-select: none;
27
+ -webkit-tap-highlight-color: transparent;
28
+ font-family: inherit;
29
+ }
30
+ :host([block]) {
31
+ display: flex;
32
+ width: 100%;
33
+ }
34
+
35
+ /* ── Base ── */
36
+ .btn {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ gap: var(--btn-gap, 8px);
41
+ padding: var(--btn-py, 6px) var(--btn-px, 16px);
42
+ border: 1px solid transparent;
43
+ border-radius: var(--btn-radius, 6px);
44
+ font-size: var(--btn-font, 13px);
45
+ font-weight: 500;
46
+ line-height: 1;
47
+ cursor: pointer;
48
+ transition: all var(--lux-transition, 150ms ease);
49
+ white-space: nowrap;
50
+ }
51
+ :host(:not([block])) .btn {
52
+ width: 100%;
53
+ box-sizing: border-box;
54
+ }
55
+ .btn:active {
56
+ transform: translateY(1px);
57
+ }
58
+
59
+ /* ── Default (primary solid) ── */
60
+ .btn {
61
+ background: rgb(var(--lux-primary-500));
62
+ color: #fff;
63
+ border-color: rgb(var(--lux-primary-500));
64
+ }
65
+ .btn:hover {
66
+ background: rgb(var(--lux-primary-600));
67
+ border-color: rgb(var(--lux-primary-600));
68
+ }
69
+ .btn:active {
70
+ background: rgb(var(--lux-primary-700));
71
+ }
72
+
73
+ /* ── Color variants (solid) ── */
74
+ :host([variant='secondary']) .btn {
75
+ background: rgb(var(--lux-card));
76
+ color: rgb(var(--lux-text));
77
+ border-color: rgb(var(--lux-border));
78
+ }
79
+ :host([variant='secondary']) .btn:hover {
80
+ background: rgb(var(--lux-hover));
81
+ border-color: rgb(var(--lux-border-hover));
82
+ }
83
+
84
+ :host([variant='success']) .btn {
85
+ background: rgb(var(--lux-success));
86
+ color: #fff;
87
+ border-color: rgb(var(--lux-success));
88
+ }
89
+ :host([variant='success']) .btn:hover {
90
+ background: rgb(22 163 74);
91
+ }
92
+
93
+ :host([variant='warning']) .btn {
94
+ background: rgb(var(--lux-warning));
95
+ color: #fff;
96
+ border-color: rgb(var(--lux-warning));
97
+ }
98
+ :host([variant='warning']) .btn:hover {
99
+ background: rgb(217 119 6);
100
+ }
101
+
102
+ :host([variant='error']) .btn,
103
+ :host([variant='danger']) .btn {
104
+ background: rgb(var(--lux-error));
105
+ color: #fff;
106
+ border-color: rgb(var(--lux-error));
107
+ }
108
+ :host([variant='error']) .btn:hover,
109
+ :host([variant='danger']) .btn:hover {
110
+ background: rgb(239 68 68);
111
+ }
112
+
113
+ :host([variant='info']) .btn {
114
+ background: rgb(var(--lux-info));
115
+ color: #fff;
116
+ border-color: rgb(var(--lux-info));
117
+ }
118
+ :host([variant='info']) .btn:hover {
119
+ background: rgb(37 99 235);
120
+ }
121
+
122
+ /* ── Outline (transparent bg, colored border/text) ── */
123
+ :host([outline]) .btn {
124
+ background: transparent;
125
+ color: rgb(var(--lux-primary-500));
126
+ border-color: rgb(var(--lux-primary-500));
127
+ }
128
+ :host([outline]) .btn:hover {
129
+ background: rgb(var(--lux-primary-500) / 10%);
130
+ }
131
+ :host([outline]) .btn:active {
132
+ background: rgb(var(--lux-primary-500) / 18%);
133
+ }
134
+
135
+ :host([outline][variant='secondary']) .btn {
136
+ color: rgb(var(--lux-text));
137
+ border-color: rgb(var(--lux-border));
138
+ }
139
+ :host([outline][variant='secondary']) .btn:hover {
140
+ background: rgb(var(--lux-hover));
141
+ }
142
+
143
+ :host([outline][variant='success']) .btn {
144
+ color: rgb(var(--lux-success));
145
+ border-color: rgb(var(--lux-success));
146
+ }
147
+ :host([outline][variant='success']) .btn:hover {
148
+ background: rgb(var(--lux-success) / 10%);
149
+ }
150
+
151
+ :host([outline][variant='warning']) .btn {
152
+ color: rgb(var(--lux-warning));
153
+ border-color: rgb(var(--lux-warning));
154
+ }
155
+ :host([outline][variant='warning']) .btn:hover {
156
+ background: rgb(var(--lux-warning) / 10%);
157
+ }
158
+
159
+ :host([outline][variant='error']) .btn,
160
+ :host([outline][variant='danger']) .btn {
161
+ color: rgb(var(--lux-error));
162
+ border-color: rgb(var(--lux-error));
163
+ }
164
+ :host([outline][variant='error']) .btn:hover,
165
+ :host([outline][variant='danger']) .btn:hover {
166
+ background: rgb(var(--lux-error) / 10%);
167
+ }
168
+
169
+ :host([outline][variant='info']) .btn {
170
+ color: rgb(var(--lux-info));
171
+ border-color: rgb(var(--lux-info));
172
+ }
173
+ :host([outline][variant='info']) .btn:hover {
174
+ background: rgb(var(--lux-info) / 10%);
175
+ }
176
+
177
+ /* ── Ghost (transparent, no border, colored text) ── */
178
+ :host([ghost]) .btn {
179
+ background: transparent;
180
+ border-color: transparent;
181
+ color: rgb(var(--lux-primary-500));
182
+ }
183
+ :host([ghost]) .btn:hover {
184
+ background: rgb(var(--lux-primary-500) / 10%);
185
+ }
186
+ :host([ghost]) .btn:active {
187
+ background: rgb(var(--lux-primary-500) / 18%);
188
+ }
189
+
190
+ :host([ghost][variant='secondary']) .btn {
191
+ color: rgb(var(--lux-text));
192
+ }
193
+ :host([ghost][variant='secondary']) .btn:hover {
194
+ background: rgb(var(--lux-hover));
195
+ }
196
+
197
+ :host([ghost][variant='success']) .btn {
198
+ color: rgb(var(--lux-success));
199
+ }
200
+ :host([ghost][variant='success']) .btn:hover {
201
+ background: rgb(var(--lux-success) / 10%);
202
+ }
203
+
204
+ :host([ghost][variant='warning']) .btn {
205
+ color: rgb(var(--lux-warning));
206
+ }
207
+ :host([ghost][variant='warning']) .btn:hover {
208
+ background: rgb(var(--lux-warning) / 10%);
209
+ }
210
+
211
+ :host([ghost][variant='error']) .btn,
212
+ :host([ghost][variant='danger']) .btn {
213
+ color: rgb(var(--lux-error));
214
+ }
215
+ :host([ghost][variant='error']) .btn:hover,
216
+ :host([ghost][variant='danger']) .btn:hover {
217
+ background: rgb(var(--lux-error) / 10%);
218
+ }
219
+
220
+ :host([ghost][variant='info']) .btn {
221
+ color: rgb(var(--lux-info));
222
+ }
223
+ :host([ghost][variant='info']) .btn:hover {
224
+ background: rgb(var(--lux-info) / 10%);
225
+ }
226
+
227
+ /* ── Size ── */
228
+ :host([size='sm']) .btn {
229
+ --btn-py: 4px;
230
+ --btn-px: 12px;
231
+ --btn-font: 12px;
232
+ --btn-gap: 4px;
233
+ }
234
+ :host([size='lg']) .btn {
235
+ --btn-py: 10px;
236
+ --btn-px: 20px;
237
+ --btn-font: 15px;
238
+ --btn-gap: 10px;
239
+ }
240
+
241
+ /* ── Shape: circle ── */
242
+ :host([shape='circle']) .btn {
243
+ border-radius: 50%;
244
+ --btn-px: 0;
245
+ width: var(--icon-size, 36px);
246
+ height: var(--icon-size, 36px);
247
+ padding: 0;
248
+ }
249
+ :host([shape='circle'][size='sm']) .btn {
250
+ --icon-size: 32px;
251
+ }
252
+ :host([shape='circle'][size='lg']) .btn {
253
+ --icon-size: 44px;
254
+ }
255
+
256
+ /* ── Shape: square ── */
257
+ :host([shape='square']) .btn {
258
+ --btn-px: 0;
259
+ width: var(--icon-size, 36px);
260
+ height: var(--icon-size, 36px);
261
+ padding: 0;
262
+ }
263
+ :host([shape='square'][size='sm']) .btn {
264
+ --icon-size: 32px;
265
+ }
266
+ :host([shape='square'][size='lg']) .btn {
267
+ --icon-size: 44px;
268
+ }
269
+
270
+ /* ── Loading ── */
271
+ .spinner {
272
+ width: 1em;
273
+ height: 1em;
274
+ border: 2px solid currentColor;
275
+ border-top-color: transparent;
276
+ border-radius: 50%;
277
+ animation: lux-spin 0.6s linear infinite;
278
+ }
279
+ @keyframes lux-spin {
280
+ to {
281
+ transform: rotate(360deg);
282
+ }
283
+ }
284
+ `;
285
+
286
+ class LuxButton extends LuxElement {
287
+ static styles = styles;
288
+
289
+ static properties = {
290
+ variant: { type: String, reflect: true },
291
+ size: { type: String, reflect: true },
292
+ shape: { type: String, reflect: true },
293
+ icon: { type: String, reflect: true },
294
+ disabled: { type: Boolean, reflect: true },
295
+ loading: { type: Boolean, reflect: true },
296
+ block: { type: Boolean, reflect: true },
297
+ outline: { type: Boolean, reflect: true },
298
+ ghost: { type: Boolean, reflect: true },
299
+ };
300
+
301
+ constructor() {
302
+ super();
303
+ this.variant = 'primary';
304
+ this.size = 'md';
305
+ }
306
+
307
+ render() {
308
+ const hasIcon = !!this.icon;
309
+ return html`
310
+ <div class="btn">
311
+ ${this.loading ? html`<span class="spinner"></span>` : hasIcon ? html`<lux-icon name=${this.icon}></lux-icon>` : ''}
312
+ ${hasIcon ? '' : html`<slot></slot>`}
313
+ </div>
314
+ `;
315
+ }
316
+ }
317
+
318
+ registerComponent('lux-button', LuxButton);
319
+ export default LuxButton;