@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
@@ -0,0 +1,349 @@
1
+ /**
2
+ * lux-scroll — Custom scrollbar container.
3
+ *
4
+ * Hides native scrollbar and shows a styled custom scrollbar.
5
+ * Supports scroll-to-top/bottom buttons and theme-aware colors.
6
+ *
7
+ * Usage:
8
+ * <lux-scroll height="400px">
9
+ * <div>Long content...</div>
10
+ * </lux-scroll>
11
+ * <lux-scroll height="100%" show-buttons>
12
+ * <div>Content with scroll buttons</div>
13
+ * </lux-scroll>
14
+ *
15
+ * Props:
16
+ * height — container height (default: 100%)
17
+ * width — container width (default: 100%)
18
+ * show-buttons — show scroll-to-top/bottom buttons
19
+ * disabled — disable custom scrollbar (show native)
20
+ */
21
+
22
+ import { html, css, LuxElement, registerComponent } from '../../index.js';
23
+
24
+ const styles = css`
25
+ :host {
26
+ display: block;
27
+ position: relative;
28
+ width: var(--scroll-w, 100%);
29
+ height: var(--scroll-h, 100%);
30
+ }
31
+
32
+ .scroll-container {
33
+ width: 100%;
34
+ height: 100%;
35
+ overflow-y: auto;
36
+ overflow-x: hidden;
37
+ position: relative;
38
+ scrollbar-width: none;
39
+ -ms-overflow-style: none;
40
+ }
41
+
42
+ .scroll-container::-webkit-scrollbar {
43
+ display: none;
44
+ }
45
+
46
+ /* ── Custom Track ── */
47
+ .scroll-track {
48
+ position: absolute;
49
+ top: 4px;
50
+ right: 4px;
51
+ width: 6px;
52
+ height: calc(100% - 8px);
53
+ background: rgb(var(--lux-border, 226 232 240) / 0.2);
54
+ border-radius: 3px;
55
+ z-index: 10;
56
+ opacity: 0;
57
+ transition: opacity 0.2s ease;
58
+ }
59
+
60
+ :host(:hover) .scroll-track,
61
+ .scroll-container:hover + .scroll-track,
62
+ .scroll-track.visible {
63
+ opacity: 1;
64
+ }
65
+
66
+ /* ── Custom Thumb ── */
67
+ .scroll-thumb {
68
+ position: absolute;
69
+ top: 0;
70
+ left: 0;
71
+ width: 100%;
72
+ border-radius: 3px;
73
+ background: rgb(var(--lux-scrollbar, 180 196 214));
74
+ cursor: grab;
75
+ transition:
76
+ background 0.15s ease,
77
+ height 0.15s ease;
78
+ min-height: 20px;
79
+ }
80
+
81
+ .scroll-thumb:hover,
82
+ .scroll-thumb.dragging {
83
+ background: rgb(var(--lux-primary-400, 129 120 247));
84
+ }
85
+
86
+ .scroll-thumb.dragging {
87
+ cursor: grabbing;
88
+ }
89
+
90
+ /* ── Scroll Buttons ─── */
91
+ .scroll-buttons {
92
+ position: absolute;
93
+ top: 8px;
94
+ right: 8px;
95
+ display: flex;
96
+ flex-direction: column;
97
+ gap: 4px;
98
+ z-index: 11;
99
+ opacity: 0;
100
+ transition: opacity 0.2s ease;
101
+ }
102
+
103
+ :host(:hover) .scroll-buttons,
104
+ .scroll-buttons.visible {
105
+ opacity: 1;
106
+ }
107
+
108
+ .scroll-btn {
109
+ width: 28px;
110
+ height: 28px;
111
+ border-radius: 50%;
112
+ border: 1px solid rgb(var(--lux-border, 51 65 85));
113
+ background: rgb(var(--lux-card, 30 41 59));
114
+ color: rgb(var(--lux-text-secondary, 148 163 184));
115
+ cursor: pointer;
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ font-size: 12px;
120
+ transition: all 0.15s ease;
121
+ padding: 0;
122
+ }
123
+
124
+ .scroll-btn:hover {
125
+ background: rgb(var(--lux-primary-400, 129 120 247));
126
+ color: #fff;
127
+ border-color: rgb(var(--lux-primary-400, 129 120 247));
128
+ }
129
+
130
+ .scroll-btn:disabled {
131
+ opacity: 0.3;
132
+ pointer-events: none;
133
+ }
134
+
135
+ /* ── Disabled (show native) ── */
136
+ :host([disabled]) .scroll-track,
137
+ :host([disabled]) .scroll-buttons {
138
+ display: none;
139
+ }
140
+ :host([disabled]) .scroll-container {
141
+ scrollbar-width: auto;
142
+ -ms-overflow-style: auto;
143
+ }
144
+ :host([disabled]) .scroll-container::-webkit-scrollbar {
145
+ display: block;
146
+ }
147
+ `;
148
+
149
+ class LuxScroll extends LuxElement {
150
+ static styles = styles;
151
+
152
+ static properties = {
153
+ height: { type: String, attribute: 'height', reflect: true },
154
+ width: { type: String, attribute: 'width', reflect: true },
155
+ showButtons: { type: Boolean, attribute: 'show-buttons', reflect: true },
156
+ disabled: { type: Boolean, attribute: 'disabled', reflect: true },
157
+ };
158
+
159
+ constructor() {
160
+ super();
161
+ this.height = '100%';
162
+ this.width = '100%';
163
+ this.showButtons = false;
164
+ this.disabled = false;
165
+ }
166
+
167
+ connectedCallback() {
168
+ super.connectedCallback();
169
+ this.style.height = this.height;
170
+ this.style.width = this.width;
171
+ }
172
+
173
+ firstUpdated() {
174
+ this._setupScroll();
175
+ }
176
+
177
+ updated() {
178
+ this.style.height = this.height;
179
+ this.style.width = this.width;
180
+ requestAnimationFrame(() => this._syncThumb());
181
+ }
182
+
183
+ disconnectedCallback() {
184
+ super.disconnectedCallback();
185
+ this._teardownScroll();
186
+ }
187
+
188
+ _setupScroll() {
189
+ const container = this.renderRoot.querySelector('.scroll-container');
190
+ const thumb = this.renderRoot.querySelector('.scroll-thumb');
191
+ const track = this.renderRoot.querySelector('.scroll-track');
192
+ if (!container || !thumb || !track) return;
193
+
194
+ this._container = container;
195
+ this._thumb = thumb;
196
+ this._track = track;
197
+
198
+ // Sync thumb position on scroll
199
+ this._onScroll = () => this._syncThumb();
200
+ container.addEventListener('scroll', this._onScroll, { passive: true });
201
+
202
+ // Drag thumb
203
+ this._onThumbDown = (e) => this._startDrag(e);
204
+ thumb.addEventListener('mousedown', this._onThumbDown);
205
+
206
+ // Click track to scroll
207
+ this._onTrackClickBound = (e) => this._onTrackClick(e);
208
+ track.addEventListener('click', this._onTrackClickBound);
209
+
210
+ // Show/hide on hover
211
+ this._onMouseEnter = () => {
212
+ track.classList.add('visible');
213
+ this._showButtons(true);
214
+ };
215
+ this._onMouseLeave = () => {
216
+ track.classList.remove('visible');
217
+ this._showButtons(false);
218
+ };
219
+ this.addEventListener('mouseenter', this._onMouseEnter);
220
+ this.addEventListener('mouseleave', this._onMouseLeave);
221
+
222
+ // Initial sync
223
+ requestAnimationFrame(() => this._syncThumb());
224
+ }
225
+
226
+ _teardownScroll() {
227
+ if (this._container) {
228
+ this._container.removeEventListener('scroll', this._onScroll);
229
+ }
230
+ if (this._thumb) {
231
+ this._thumb.removeEventListener('mousedown', this._onThumbDown);
232
+ }
233
+ if (this._track) {
234
+ this._track.removeEventListener('click', this._onTrackClickBound);
235
+ }
236
+ this.removeEventListener('mouseenter', this._onMouseEnter);
237
+ this.removeEventListener('mouseleave', this._onMouseLeave);
238
+ }
239
+
240
+ _syncThumb() {
241
+ const c = this._container;
242
+ const t = this._thumb;
243
+ const track = this._track;
244
+ if (!c || !t || !track) return;
245
+
246
+ const scrollH = c.scrollHeight;
247
+ const clientH = c.clientHeight;
248
+ const trackH = track.offsetHeight || clientH - 8;
249
+ if (scrollH <= clientH) {
250
+ t.style.height = '0px';
251
+ t.style.opacity = '0';
252
+ return;
253
+ }
254
+
255
+ const ratio = clientH / scrollH;
256
+ const thumbH = Math.max(20, trackH * ratio);
257
+ const maxTop = trackH - thumbH;
258
+ const scrollTop = c.scrollTop;
259
+ const maxScroll = scrollH - clientH;
260
+ const top = maxScroll > 0 ? (scrollTop / maxScroll) * maxTop : 0;
261
+
262
+ t.style.height = thumbH + 'px';
263
+ t.style.top = top + 'px';
264
+ t.style.opacity = '1';
265
+ }
266
+
267
+ _startDrag(e) {
268
+ e.preventDefault();
269
+ const c = this._container;
270
+ const t = this._thumb;
271
+ if (!c || !t) return;
272
+
273
+ const startY = e.clientY;
274
+ const startScroll = c.scrollTop;
275
+ const scrollH = c.scrollHeight;
276
+ const clientH = c.clientHeight;
277
+ const thumbH = t.offsetHeight;
278
+ const maxScroll = scrollH - clientH;
279
+ const maxTop = clientH - thumbH;
280
+ const ratio = maxScroll > maxTop ? maxScroll / maxTop : 1;
281
+
282
+ t.classList.add('dragging');
283
+
284
+ const onMove = (ev) => {
285
+ const dy = ev.clientY - startY;
286
+ const newScroll = startScroll + dy * ratio;
287
+ c.scrollTop = Math.max(0, Math.min(maxScroll, newScroll));
288
+ };
289
+
290
+ const onUp = () => {
291
+ t.classList.remove('dragging');
292
+ document.removeEventListener('mousemove', onMove);
293
+ document.removeEventListener('mouseup', onUp);
294
+ };
295
+
296
+ document.addEventListener('mousemove', onMove);
297
+ document.addEventListener('mouseup', onUp);
298
+ }
299
+
300
+ _onTrackClick(e) {
301
+ const c = this._container;
302
+ if (!c) return;
303
+ const rect = this._track.getBoundingClientRect();
304
+ const clickY = e.clientY - rect.top;
305
+ const trackH = rect.height;
306
+ const ratio = clickY / trackH;
307
+ const maxScroll = c.scrollHeight - c.clientHeight;
308
+ c.scrollTop = ratio * maxScroll;
309
+ }
310
+
311
+ _showButtons(show) {
312
+ if (!this.showButtons) return;
313
+ const btns = this.renderRoot.querySelector('.scroll-buttons');
314
+ if (btns) btns.classList.toggle('visible', show);
315
+ }
316
+
317
+ scrollToTop() {
318
+ this._container?.scrollTo({ top: 0, behavior: 'smooth' });
319
+ }
320
+
321
+ scrollToBottom() {
322
+ const c = this._container;
323
+ if (c) c.scrollTo({ top: c.scrollHeight, behavior: 'smooth' });
324
+ }
325
+
326
+ render() {
327
+ return html`
328
+ <div class="scroll-container">
329
+ <slot></slot>
330
+ </div>
331
+ <div class="scroll-track">
332
+ <div class="scroll-thumb"></div>
333
+ </div>
334
+ ${
335
+ this.showButtons
336
+ ? html`
337
+ <div class="scroll-buttons">
338
+ <button class="scroll-btn" @click=${() => this.scrollToTop()}>▲</button>
339
+ <button class="scroll-btn" @click=${() => this.scrollToBottom()}>▼</button>
340
+ </div>
341
+ `
342
+ : ''
343
+ }
344
+ `;
345
+ }
346
+ }
347
+
348
+ registerComponent('lux-scroll', LuxScroll);
349
+ export default LuxScroll;
@@ -0,0 +1,203 @@
1
+ /**
2
+ * lux-switch — Toggle switch component.
3
+ *
4
+ * Usage:
5
+ * <lux-switch checked></lux-switch>
6
+ * <lux-switch checked size="lg" shape="square"></lux-switch>
7
+ * <lux-switch checked-on-color="#10b981" checked-off-color="#ef4444">ON/OFF</lux-switch>
8
+ *
9
+ * Props:
10
+ * checked — switch state
11
+ * disabled — disable interaction
12
+ * size — sm / md / lg
13
+ * shape — round (default) / square
14
+ * checked-on-bg — background when checked
15
+ * checked-on-color — text/icon color when checked
16
+ * checked-off-bg — background when unchecked
17
+ * checked-off-color — text/icon color when unchecked
18
+ *
19
+ * Events:
20
+ * change — detail: { checked: boolean }
21
+ */
22
+
23
+ import { html, css, LuxElement, registerComponent } from '../../index.js';
24
+
25
+ const styles = css`
26
+ :host {
27
+ display: inline-flex;
28
+ align-items: center;
29
+ gap: 8px;
30
+ cursor: pointer;
31
+ vertical-align: middle;
32
+ user-select: none;
33
+ -webkit-tap-highlight-color: transparent;
34
+ }
35
+
36
+ :host([disabled]) {
37
+ opacity: 0.5;
38
+ pointer-events: none;
39
+ }
40
+
41
+ :host([loading]) {
42
+ pointer-events: none;
43
+ }
44
+
45
+ .track {
46
+ position: relative;
47
+ width: var(--sw-w, 40px);
48
+ height: var(--sw-h, 22px);
49
+ background: var(--sw-off-bg, rgb(var(--lux-border, 51 65 85)));
50
+ border: none;
51
+ padding: 0;
52
+ cursor: pointer;
53
+ transition: background var(--lux-transition, 150ms ease);
54
+ flex-shrink: 0;
55
+ }
56
+
57
+ :host([checked]) .track {
58
+ background: var(--sw-on-bg, rgb(var(--lux-primary-500, 99 91 218)));
59
+ }
60
+
61
+ .thumb {
62
+ position: absolute;
63
+ top: calc((var(--sw-h, 22px) - var(--sw-thumb, 18px)) / 2);
64
+ left: calc((var(--sw-h, 22px) - var(--sw-thumb, 18px)) / 2);
65
+ width: var(--sw-thumb, 18px);
66
+ height: var(--sw-thumb, 18px);
67
+ background: var(--sw-thumb-bg, rgb(var(--lux-bg, 255 255 255)));
68
+ border-radius: inherit;
69
+ transition: transform var(--lux-transition, 150ms ease);
70
+ box-shadow: 0 1px 3px rgb(0 0 0 / 20%);
71
+ }
72
+
73
+ :host([checked]) .thumb {
74
+ transform: translateX(calc(var(--sw-w, 40px) - var(--sw-h, 22px)));
75
+ }
76
+
77
+ .content {
78
+ font-size: var(--sw-font, 14px);
79
+ color: var(--sw-off-color, rgb(var(--lux-text, 241 245 249)));
80
+ transition: color var(--lux-transition, 150ms ease);
81
+ }
82
+
83
+ :host([checked]) .content {
84
+ color: var(--sw-on-color, rgb(var(--lux-text, 241 245 249)));
85
+ }
86
+
87
+ /* ── Size: sm ── */
88
+ :host([size='sm']) .track {
89
+ --sw-w: 32px;
90
+ --sw-h: 18px;
91
+ --sw-thumb: 14px;
92
+ --sw-font: 12px;
93
+ }
94
+
95
+ /* ── Size: md (default) ── */
96
+ /* uses CSS variables above */
97
+
98
+ /* ── Size: lg ── */
99
+ :host([size='lg']) .track {
100
+ --sw-w: 52px;
101
+ --sw-h: 28px;
102
+ --sw-thumb: 22px;
103
+ --sw-font: 16px;
104
+ }
105
+
106
+ /* ── Shape: square ── */
107
+ :host([shape='square']) .track,
108
+ :host([shape='square']) .thumb {
109
+ border-radius: 4px;
110
+ }
111
+
112
+ /* ── Shape: round (default) ── */
113
+ .track {
114
+ border-radius: 9999px;
115
+ }
116
+ .thumb {
117
+ border-radius: 9999px;
118
+ }
119
+
120
+ /* ── Loading ── */
121
+ :host([loading]) .thumb::after {
122
+ content: '';
123
+ position: absolute;
124
+ inset: 1px;
125
+ border: 2px solid rgb(var(--lux-border, 51 65 85) / 0.2);
126
+ border-top-color: rgb(var(--lux-text, 241 245 249));
127
+ border-radius: 50%;
128
+ animation: sw-spin 0.8s linear infinite;
129
+ }
130
+ @keyframes sw-spin {
131
+ to {
132
+ transform: rotate(360deg);
133
+ }
134
+ }
135
+ `;
136
+
137
+ class LuxSwitch extends LuxElement {
138
+ static styles = styles;
139
+
140
+ static properties = {
141
+ checked: { type: Boolean, reflect: true },
142
+ disabled: { type: Boolean, reflect: true },
143
+ loading: { type: Boolean, reflect: true },
144
+ size: { type: String, reflect: true },
145
+ shape: { type: String, reflect: true },
146
+ checkedOnBg: { type: String, attribute: 'checked-on-bg', reflect: true },
147
+ checkedOnColor: { type: String, attribute: 'checked-on-color', reflect: true },
148
+ checkedOffBg: { type: String, attribute: 'checked-off-bg', reflect: true },
149
+ checkedOffColor: { type: String, attribute: 'checked-off-color', reflect: true },
150
+ toggle: { type: Function, attribute: false },
151
+ };
152
+
153
+ constructor() {
154
+ super();
155
+ this.checked = false;
156
+ this.disabled = false;
157
+ this.loading = false;
158
+ this.size = 'md';
159
+ this.shape = 'round';
160
+ }
161
+
162
+ updated() {
163
+ const s = this.style;
164
+ if (this.checkedOnBg) s.setProperty('--sw-on-bg', this.checkedOnBg);
165
+ if (this.checkedOnColor) s.setProperty('--sw-on-color', this.checkedOnColor);
166
+ if (this.checkedOffBg) s.setProperty('--sw-off-bg', this.checkedOffBg);
167
+ if (this.checkedOffColor) s.setProperty('--sw-off-color', this.checkedOffColor);
168
+ }
169
+
170
+ async _toggle() {
171
+ if (this.disabled || this.loading) return;
172
+
173
+ if (typeof this.toggle === 'function') {
174
+ this.loading = true;
175
+ try {
176
+ const result = await this.toggle();
177
+ if (result === true) {
178
+ this.checked = !this.checked;
179
+ }
180
+ } catch {
181
+ // error — don't toggle
182
+ } finally {
183
+ this.loading = false;
184
+ }
185
+ } else {
186
+ this.checked = !this.checked;
187
+ }
188
+
189
+ this.emit('change', { checked: this.checked });
190
+ }
191
+
192
+ render() {
193
+ return html`
194
+ <div class="track" @click=${() => this._toggle()}>
195
+ <div class="thumb"></div>
196
+ </div>
197
+ <div class="content"><slot></slot></div>
198
+ `;
199
+ }
200
+ }
201
+
202
+ registerComponent('lux-switch', LuxSwitch);
203
+ export default LuxSwitch;
@@ -0,0 +1,105 @@
1
+ /**
2
+ * lux-table — Table component.
3
+ *
4
+ * Props:
5
+ * border, stripe, row-border, col-border, size, hover
6
+ */
7
+
8
+ import { html, css, LuxElement, registerComponent } from '../../index.js';
9
+
10
+ const styles = css`
11
+ :host {
12
+ display: block;
13
+ width: 100%;
14
+ margin: 12px 0;
15
+ }
16
+ table {
17
+ width: 100%;
18
+ border-collapse: collapse;
19
+ font-size: 14px;
20
+ }
21
+ th,
22
+ td {
23
+ padding: 10px 16px;
24
+ text-align: left;
25
+ vertical-align: top;
26
+ }
27
+ th {
28
+ color: rgb(var(--lux-text-muted, 100 116 139));
29
+ font-weight: 500;
30
+ font-size: 12px;
31
+ text-transform: uppercase;
32
+ letter-spacing: 1px;
33
+ background: rgb(var(--lux-bg-alt, 30 41 59));
34
+ }
35
+ td {
36
+ color: rgb(var(--lux-text-secondary, 148 163 184));
37
+ }
38
+ code {
39
+ font-family: 'SF Mono', Consolas, monospace;
40
+ font-size: 0.88em;
41
+ background: rgb(var(--lux-bg-alt, 30 41 59));
42
+ padding: 2px 6px;
43
+ border-radius: 4px;
44
+ }
45
+ :host([size='sm']) table {
46
+ font-size: 13px;
47
+ }
48
+ :host([size='sm']) th,
49
+ :host([size='sm']) td {
50
+ padding: 6px 12px;
51
+ }
52
+ :host([size='lg']) table {
53
+ font-size: 15px;
54
+ }
55
+ :host([size='lg']) th,
56
+ :host([size='lg']) td {
57
+ padding: 14px 20px;
58
+ }
59
+ :host([border]) table {
60
+ border: 1px solid rgb(var(--lux-border, 51 65 85));
61
+ }
62
+ :host([row-border]) th,
63
+ :host([row-border]) td {
64
+ border-bottom: 1px solid rgb(var(--lux-border, 51 65 85));
65
+ }
66
+ :host([col-border]) td + td,
67
+ :host([col-border]) th + th {
68
+ border-left: 1px solid rgb(var(--lux-border, 51 65 85));
69
+ }
70
+ :host([stripe]) tbody tr:nth-child(even) {
71
+ background: rgb(var(--lux-hover, 255 255 255 / 3%));
72
+ }
73
+ :host([hover]) tbody tr:hover {
74
+ background: rgb(var(--lux-hover, 255 255 255 / 5%));
75
+ }
76
+ `;
77
+
78
+ class LuxTable extends LuxElement {
79
+ static styles = styles;
80
+
81
+ static properties = {
82
+ border: { type: Boolean, reflect: true },
83
+ stripe: { type: Boolean, reflect: true },
84
+ rowBorder: { type: Boolean, attribute: 'row-border', reflect: true },
85
+ colBorder: { type: Boolean, attribute: 'col-border', reflect: true },
86
+ size: { type: String, reflect: true },
87
+ hover: { type: Boolean, reflect: true },
88
+ };
89
+
90
+ firstUpdated() {
91
+ const table = this.renderRoot.querySelector('table');
92
+ if (table) {
93
+ while (this.firstChild) {
94
+ table.appendChild(this.firstChild);
95
+ }
96
+ }
97
+ }
98
+
99
+ render() {
100
+ return html`<table></table>`;
101
+ }
102
+ }
103
+
104
+ registerComponent('lux-table', LuxTable);
105
+ export default LuxTable;
package/src/core.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Lux Core — template engine + element base class
3
+ * Use this when you need Web Components but not router/i18n/theme.
4
+ */
5
+ export { html, svg, css, render, isTemplateResult, nothing, escapeHtml } from './template.js';
6
+ export { repeat, when, show, classMap, styleMap, guard } from './template.js';
7
+ export { LuxElement, registerComponent, createComponent } from './element.js';