@reliability-design/web 1.0.6 → 1.2.0
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/dist/components/rel-accordion/rel-accordion.ts +20 -31
- package/dist/components/rel-alert/rel-alert.ts +81 -11
- package/dist/components/rel-avatar/rel-avatar.ts +6 -3
- package/dist/components/rel-badge/rel-badge.ts +8 -3
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +6 -6
- package/dist/components/rel-button/rel-button.ts +118 -16
- package/dist/components/rel-calendar/rel-calendar.ts +16 -9
- package/dist/components/rel-card/rel-card.ts +9 -17
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +20 -23
- package/dist/components/rel-carousel/rel-carousel.ts +596 -469
- package/dist/components/rel-checkbox/rel-checkbox.ts +98 -15
- package/dist/components/rel-chip/rel-chip.ts +291 -186
- package/dist/components/rel-container/rel-container.ts +2 -2
- package/dist/components/rel-date-picker/rel-date-picker.ts +23 -19
- package/dist/components/rel-divider/rel-divider.ts +12 -3
- package/dist/components/rel-drawer/rel-drawer-footer.ts +27 -0
- package/dist/components/rel-drawer/rel-drawer.ts +57 -113
- package/dist/components/rel-kbd/rel-kbd.ts +94 -118
- package/dist/components/rel-layout/rel-layout.ts +49 -58
- package/dist/components/rel-menu/rel-menu.ts +359 -327
- package/dist/components/rel-menubar/rel-menubar-menu.css +3 -0
- package/dist/components/rel-menubar/rel-menubar-menu.ts +2 -1
- package/dist/components/rel-menubar/rel-menubar.ts +602 -576
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +240 -143
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +227 -331
- package/dist/components/rel-navbar/rel-navbar.ts +13 -0
- package/dist/components/rel-otp/rel-otp.ts +22 -25
- package/dist/components/rel-pagination/rel-pagination.ts +112 -63
- package/dist/components/rel-popover/rel-popover-content.ts +6 -5
- package/dist/components/rel-popover/rel-popover.ts +42 -20
- package/dist/components/rel-progress/rel-progress.ts +10 -9
- package/dist/components/rel-radio/rel-radio.ts +228 -155
- package/dist/components/rel-range-picker/rel-range-picker.css +349 -0
- package/dist/components/rel-range-picker/rel-range-picker.ts +1079 -0
- package/dist/components/rel-resizable/rel-resizable-handle.ts +12 -15
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +41 -20
- package/dist/components/rel-select/rel-select.ts +112 -27
- package/dist/components/rel-sheet/rel-sheet.ts +362 -683
- package/dist/components/rel-sidebar/rel-sidebar.ts +13 -5
- package/dist/components/rel-slider/rel-slider.ts +74 -29
- package/dist/components/rel-snackbar/rel-snackbar.ts +67 -37
- package/dist/components/rel-stepper/rel-stepper.ts +43 -31
- package/dist/components/rel-switch/rel-switch.ts +26 -12
- package/dist/components/rel-tab/rel-tab.ts +57 -37
- package/dist/components/rel-table/rel-table-body.ts +5 -0
- package/dist/components/rel-table/rel-table-caption.ts +6 -1
- package/dist/components/rel-table/rel-table-cell.ts +42 -49
- package/dist/components/rel-table/rel-table-footer.ts +5 -0
- package/dist/components/rel-table/rel-table-head.ts +13 -1
- package/dist/components/rel-table/rel-table-header.ts +5 -0
- package/dist/components/rel-table/rel-table-row.ts +7 -3
- package/dist/components/rel-table/rel-table.ts +8 -2
- package/dist/components/rel-textfield/rel-textfield.ts +153 -44
- package/dist/components/rel-toast/rel-toast.ts +56 -22
- package/dist/components/rel-tooltip/rel-tooltip.ts +52 -9
- package/dist/components/rel-topbar/rel-topbar-actions.ts +24 -0
- package/dist/components/rel-topbar/rel-topbar-brand.ts +47 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +63 -0
- package/dist/components/rel-topbar/rel-topbar-dropdown.ts +28 -0
- package/dist/components/rel-topbar/rel-topbar-item.ts +320 -0
- package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +24 -0
- package/dist/components/rel-topbar/rel-topbar-profile.ts +222 -0
- package/dist/components/rel-topbar/rel-topbar-utilities.ts +24 -0
- package/dist/components/rel-topbar/rel-topbar.ts +438 -0
- package/dist/index.d.mts +375 -411
- package/dist/index.d.ts +375 -411
- package/dist/index.js +7587 -7980
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7647 -8023
- package/dist/index.mjs.map +1 -1
- package/dist/rel-menubar-menu-BEEQDAXW.css +3 -0
- package/dist/styles/vars-v2.css +525 -0
- package/dist/styles/vars.css +79 -27
- package/dist/{vars-ITL2K3KO.css → vars-I2PC74XD.css} +79 -27
- package/dist/vars-v2-VMGWTFJZ.css +525 -0
- package/package.json +3 -1
- package/dist/components/rel-quote-page/README.md +0 -166
- package/dist/components/rel-quote-page/rel-quote-page.ts +0 -816
|
@@ -24,8 +24,6 @@ export class RelOtp extends LitElement {
|
|
|
24
24
|
@property({ type: String }) size: "sm" | "md" | "lg" = "md";
|
|
25
25
|
|
|
26
26
|
@state() private cells: string[] = [];
|
|
27
|
-
@state() private focusedIndex: number = -1;
|
|
28
|
-
|
|
29
27
|
@query(".hidden-input") private hiddenInput?: HTMLInputElement;
|
|
30
28
|
|
|
31
29
|
private isUpdatingFromValue = false;
|
|
@@ -38,30 +36,30 @@ export class RelOtp extends LitElement {
|
|
|
38
36
|
|
|
39
37
|
:host([disabled]) {
|
|
40
38
|
opacity: 0.6;
|
|
41
|
-
|
|
39
|
+
cursor: not-allowed;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
.otp-root {
|
|
45
43
|
display: inline-flex;
|
|
46
44
|
align-items: center;
|
|
47
|
-
gap: var(--rel-spacing-space-2xs
|
|
45
|
+
gap: var(--rel-spacing-space-2xs);
|
|
48
46
|
position: relative;
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
.otp-group {
|
|
52
50
|
display: flex;
|
|
53
|
-
gap: var(--rel-spacing-space-2xs
|
|
51
|
+
gap: var(--rel-spacing-space-2xs);
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
.otp-separator {
|
|
57
55
|
display: flex;
|
|
58
56
|
align-items: center;
|
|
59
57
|
justify-content: center;
|
|
60
|
-
color: var(--rel-
|
|
58
|
+
color: var(--rel-gray-divider-default);
|
|
61
59
|
font-size: var(--rel-fontSizes-lg);
|
|
62
60
|
font-weight: var(--rel-fontWeights-semibold);
|
|
63
61
|
user-select: none;
|
|
64
|
-
padding: 0 var(--rel-spacing-space-3xs
|
|
62
|
+
padding: 0 var(--rel-spacing-space-3xs);
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
.otp-separator.hidden {
|
|
@@ -71,17 +69,17 @@ export class RelOtp extends LitElement {
|
|
|
71
69
|
.otp-cell {
|
|
72
70
|
width: 40px;
|
|
73
71
|
height: 48px;
|
|
74
|
-
border: var(--rel-borders-width-stroke-100) solid var(--rel-border-default);
|
|
72
|
+
border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);
|
|
75
73
|
border-radius: var(--rel-borders-radius-border-radius-200);
|
|
76
|
-
background: var(--rel-
|
|
74
|
+
background: var(--rel-color-bg-primary);
|
|
77
75
|
font-family: var(--rel-fontFamilies-primary);
|
|
78
76
|
font-size: var(--rel-fontSizes-lg);
|
|
79
77
|
font-weight: var(--rel-fontWeights-medium);
|
|
80
78
|
text-align: center;
|
|
81
|
-
color: var(--rel-text-primary);
|
|
79
|
+
color: var(--rel-color-text-primary);
|
|
82
80
|
outline: none;
|
|
83
81
|
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
84
|
-
caret-color: var(--rel-
|
|
82
|
+
caret-color: var(--rel-color-text-primary);
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
/* Size variants */
|
|
@@ -98,27 +96,31 @@ export class RelOtp extends LitElement {
|
|
|
98
96
|
}
|
|
99
97
|
|
|
100
98
|
.otp-cell::placeholder {
|
|
101
|
-
color: var(--rel-
|
|
99
|
+
color: var(--rel-color-text-placeholder);
|
|
102
100
|
opacity: 0.6;
|
|
103
101
|
}
|
|
104
102
|
|
|
105
103
|
.otp-cell:hover:not(:disabled):not(:read-only) {
|
|
106
|
-
border-color: var(--rel-
|
|
104
|
+
border-color: var(--rel-color-text-primary);
|
|
107
105
|
}
|
|
108
106
|
|
|
109
107
|
.otp-cell:focus-visible {
|
|
110
|
-
border-color: var(--rel-
|
|
111
|
-
box-shadow: 0 0 0 2px var(--rel-border-default);
|
|
108
|
+
border-color: var(--rel-color-text-heading);
|
|
109
|
+
box-shadow: 0 0 0 2px var(--rel-color-border-default);
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
.otp-cell:disabled {
|
|
115
|
-
background: var(--rel-
|
|
116
|
-
color: var(--rel-
|
|
113
|
+
background: var(--rel-color-bg-secondary);
|
|
114
|
+
color: var(--rel-color-text-disabled);
|
|
115
|
+
cursor: not-allowed;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
:host([disabled]) .otp-cell {
|
|
117
119
|
cursor: not-allowed;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
.otp-cell:read-only {
|
|
121
|
-
background: var(--rel-
|
|
123
|
+
background: var(--rel-color-bg-tertiary);
|
|
122
124
|
cursor: default;
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -146,6 +148,7 @@ export class RelOtp extends LitElement {
|
|
|
146
148
|
transition: none;
|
|
147
149
|
}
|
|
148
150
|
}
|
|
151
|
+
|
|
149
152
|
`;
|
|
150
153
|
|
|
151
154
|
connectedCallback() {
|
|
@@ -382,16 +385,10 @@ export class RelOtp extends LitElement {
|
|
|
382
385
|
|
|
383
386
|
private handleFocus(e: FocusEvent) {
|
|
384
387
|
const input = e.currentTarget as HTMLInputElement;
|
|
385
|
-
const index = parseInt(input.dataset.index || "0", 10);
|
|
386
|
-
|
|
387
|
-
this.focusedIndex = index;
|
|
388
|
-
|
|
389
|
-
// Select all text on focus for easy replacement
|
|
390
388
|
input.select();
|
|
391
389
|
}
|
|
392
390
|
|
|
393
391
|
private handleBlur() {
|
|
394
|
-
this.focusedIndex = -1;
|
|
395
392
|
}
|
|
396
393
|
|
|
397
394
|
private focusCell(index: number) {
|
|
@@ -458,7 +455,7 @@ export class RelOtp extends LitElement {
|
|
|
458
455
|
data-index="${index}"
|
|
459
456
|
type="${this.mask ? "password" : "text"}"
|
|
460
457
|
inputmode="${this.getInputMode()}"
|
|
461
|
-
autocomplete="
|
|
458
|
+
autocomplete="new-password"
|
|
462
459
|
pattern="${this.pattern || ""}"
|
|
463
460
|
placeholder="${this.placeholder}"
|
|
464
461
|
maxlength="1"
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { customElement, property, state } from "lit/decorators.js";
|
|
3
|
+
import "../../styles/vars-v2.css";
|
|
3
4
|
|
|
4
5
|
type DensityType = "comfortable" | "compact";
|
|
5
6
|
type VariantType = "default" | "icons";
|
|
6
|
-
type PageItem =
|
|
7
|
+
type PageItem =
|
|
8
|
+
| { type: "page"; value: number }
|
|
9
|
+
| { type: "ellipsis" }
|
|
10
|
+
| { type: "spacer" }
|
|
11
|
+
| { type: "prev" }
|
|
12
|
+
| { type: "next" };
|
|
7
13
|
|
|
8
14
|
@customElement("rel-pagination")
|
|
9
15
|
export class RelPagination extends LitElement {
|
|
10
16
|
@property({ type: Number }) page?: number;
|
|
11
17
|
@property({ type: Number }) defaultPage = 1;
|
|
12
|
-
@property({ type: Number }) totalPages
|
|
18
|
+
@property({ type: Number }) totalPages = 0;
|
|
13
19
|
@property({ type: Number }) siblingCount = 1;
|
|
14
20
|
@property({ type: Number }) boundaryCount = 1;
|
|
15
21
|
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
@@ -30,6 +36,7 @@ export class RelPagination extends LitElement {
|
|
|
30
36
|
display: flex;
|
|
31
37
|
align-items: center;
|
|
32
38
|
gap: var(--rel-spacing-space-2xs);
|
|
39
|
+
min-width: max-content;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
42
|
nav.compact {
|
|
@@ -41,35 +48,47 @@ export class RelPagination extends LitElement {
|
|
|
41
48
|
display: inline-flex;
|
|
42
49
|
align-items: center;
|
|
43
50
|
justify-content: center;
|
|
44
|
-
|
|
51
|
+
width: 40px;
|
|
45
52
|
height: 40px;
|
|
46
|
-
padding: 0
|
|
53
|
+
padding: 0;
|
|
47
54
|
font-family: var(--rel-fontFamilies-primary);
|
|
48
55
|
font-size: var(--rel-fontSizes-sm);
|
|
49
56
|
font-weight: var(--rel-fontWeights-medium);
|
|
50
|
-
color: var(--rel-
|
|
51
|
-
background: var(--rel-
|
|
52
|
-
border: var(--rel-borders-width-stroke-100) solid var(--rel-
|
|
57
|
+
color: var(--rel-color-text-heading);
|
|
58
|
+
background: var(--rel-color-bg-primary);
|
|
59
|
+
border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);
|
|
53
60
|
border-radius: var(--rel-borders-radius-border-radius-200);
|
|
54
61
|
cursor: pointer;
|
|
55
|
-
transition:
|
|
62
|
+
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
|
|
56
63
|
text-decoration: none;
|
|
57
64
|
outline: none;
|
|
58
65
|
user-select: none;
|
|
59
66
|
}
|
|
60
67
|
|
|
68
|
+
button.prev-btn, button.next-btn,
|
|
69
|
+
a.prev-btn, a.next-btn {
|
|
70
|
+
width: auto;
|
|
71
|
+
padding: 0 var(--rel-spacing-space-sm);
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
nav.compact button,
|
|
62
75
|
nav.compact a {
|
|
63
|
-
|
|
76
|
+
width: 32px;
|
|
64
77
|
height: 32px;
|
|
65
|
-
padding: 0
|
|
78
|
+
padding: 0;
|
|
66
79
|
font-size: var(--rel-fontSizes-xs);
|
|
67
80
|
}
|
|
68
81
|
|
|
82
|
+
nav.compact button.prev-btn, nav.compact button.next-btn,
|
|
83
|
+
nav.compact a.prev-btn, nav.compact a.next-btn {
|
|
84
|
+
width: auto;
|
|
85
|
+
padding: 0 var(--rel-spacing-space-xs);
|
|
86
|
+
}
|
|
87
|
+
|
|
69
88
|
button:hover:not(:disabled),
|
|
70
89
|
a:hover:not([aria-disabled="true"]) {
|
|
71
|
-
background: var(--rel-
|
|
72
|
-
border-color: var(--rel-
|
|
90
|
+
background: var(--rel-color-bg-secondary);
|
|
91
|
+
border-color: var(--rel-color-text-primary);
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
button:focus-visible,
|
|
@@ -82,40 +101,50 @@ export class RelPagination extends LitElement {
|
|
|
82
101
|
a[aria-disabled="true"] {
|
|
83
102
|
opacity: 0.5;
|
|
84
103
|
cursor: not-allowed;
|
|
85
|
-
pointer-events: none;
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
button[aria-current="page"],
|
|
89
107
|
a[aria-current="page"] {
|
|
90
|
-
background: var(--rel-
|
|
91
|
-
color: var(--rel-
|
|
92
|
-
border-color: var(--rel-
|
|
108
|
+
background: var(--rel-color-bg-selected);
|
|
109
|
+
color: var(--rel-color-text-primary);
|
|
110
|
+
border-color: var(--rel-color-text-heading);
|
|
93
111
|
font-weight: var(--rel-fontWeights-semibold);
|
|
94
112
|
}
|
|
95
113
|
|
|
96
114
|
button[aria-current="page"]:hover,
|
|
97
115
|
a[aria-current="page"]:hover {
|
|
98
|
-
background: var(--rel-
|
|
99
|
-
border-color: var(--rel-
|
|
116
|
+
background: var(--rel-color-bg-selected);
|
|
117
|
+
border-color: var(--rel-color-text-heading);
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
.ellipsis {
|
|
103
121
|
display: inline-flex;
|
|
104
122
|
align-items: center;
|
|
105
123
|
justify-content: center;
|
|
106
|
-
|
|
124
|
+
width: 40px;
|
|
107
125
|
height: 40px;
|
|
108
|
-
color: var(--rel-
|
|
126
|
+
color: var(--rel-color-text-placeholder);
|
|
109
127
|
font-size: var(--rel-fontSizes-sm);
|
|
110
128
|
user-select: none;
|
|
111
129
|
}
|
|
112
130
|
|
|
113
131
|
nav.compact .ellipsis {
|
|
114
|
-
|
|
132
|
+
width: 32px;
|
|
115
133
|
height: 32px;
|
|
116
134
|
font-size: var(--rel-fontSizes-xs);
|
|
117
135
|
}
|
|
118
136
|
|
|
137
|
+
.pagination-spacer {
|
|
138
|
+
display: inline-flex;
|
|
139
|
+
width: 40px;
|
|
140
|
+
height: 40px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
nav.compact .pagination-spacer {
|
|
144
|
+
width: 32px;
|
|
145
|
+
height: 32px;
|
|
146
|
+
}
|
|
147
|
+
|
|
119
148
|
.icon {
|
|
120
149
|
width: 16px;
|
|
121
150
|
height: 16px;
|
|
@@ -127,6 +156,10 @@ export class RelPagination extends LitElement {
|
|
|
127
156
|
height: 14px;
|
|
128
157
|
}
|
|
129
158
|
|
|
159
|
+
:host([disabled]) {
|
|
160
|
+
cursor: not-allowed;
|
|
161
|
+
}
|
|
162
|
+
|
|
130
163
|
:host([disabled]) nav {
|
|
131
164
|
opacity: 0.5;
|
|
132
165
|
pointer-events: none;
|
|
@@ -135,6 +168,19 @@ export class RelPagination extends LitElement {
|
|
|
135
168
|
|
|
136
169
|
connectedCallback() {
|
|
137
170
|
super.connectedCallback();
|
|
171
|
+
// Manually parse numeric attributes in case they were set before upgrade
|
|
172
|
+
const totalPagesAttr = this.getAttribute('total-pages');
|
|
173
|
+
if (totalPagesAttr) {
|
|
174
|
+
this.totalPages = Number(totalPagesAttr);
|
|
175
|
+
}
|
|
176
|
+
const pageAttr = this.getAttribute('page');
|
|
177
|
+
if (pageAttr) {
|
|
178
|
+
this.page = Number(pageAttr);
|
|
179
|
+
}
|
|
180
|
+
const defaultPageAttr = this.getAttribute('default-page');
|
|
181
|
+
if (defaultPageAttr) {
|
|
182
|
+
this.defaultPage = Number(defaultPageAttr);
|
|
183
|
+
}
|
|
138
184
|
this.currentPage = this.page ?? this.defaultPage;
|
|
139
185
|
}
|
|
140
186
|
|
|
@@ -153,49 +199,39 @@ export class RelPagination extends LitElement {
|
|
|
153
199
|
const items: PageItem[] = [];
|
|
154
200
|
const current = this.activePage;
|
|
155
201
|
const total = this.totalPages;
|
|
156
|
-
|
|
157
|
-
|
|
202
|
+
|
|
203
|
+
if (total <= 0) return items;
|
|
158
204
|
|
|
159
205
|
items.push({ type: "prev" });
|
|
160
206
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
{ length: Math.min(boundary, total) },
|
|
165
|
-
(_, i) => total - boundary + i + 1
|
|
166
|
-
).filter((p) => p > 0);
|
|
167
|
-
|
|
168
|
-
const leftSiblings = Array.from(
|
|
169
|
-
{ length: sibling },
|
|
170
|
-
(_, i) => current - sibling + i
|
|
171
|
-
).filter((p) => p > boundary && p < current);
|
|
172
|
-
|
|
173
|
-
const rightSiblings = Array.from(
|
|
174
|
-
{ length: sibling },
|
|
175
|
-
(_, i) => current + i + 1
|
|
176
|
-
).filter((p) => p > current && p <= total - boundary);
|
|
177
|
-
|
|
178
|
-
// Combine all visible pages
|
|
179
|
-
const visiblePages = new Set([
|
|
180
|
-
...leftBoundary,
|
|
181
|
-
...leftSiblings,
|
|
182
|
-
current,
|
|
183
|
-
...rightSiblings,
|
|
184
|
-
...rightBoundary,
|
|
185
|
-
]);
|
|
186
|
-
|
|
187
|
-
const sortedPages = Array.from(visiblePages).sort((a, b) => a - b);
|
|
188
|
-
|
|
189
|
-
// Build items with ellipsis
|
|
190
|
-
sortedPages.forEach((page, index) => {
|
|
191
|
-
if (index > 0) {
|
|
192
|
-
const prevPage = sortedPages[index - 1];
|
|
193
|
-
if (page - prevPage > 1) {
|
|
194
|
-
items.push({ type: "ellipsis" });
|
|
195
|
-
}
|
|
207
|
+
if (total <= 7) {
|
|
208
|
+
for (let i = 1; i <= total; i++) {
|
|
209
|
+
items.push({ type: "page", value: i });
|
|
196
210
|
}
|
|
197
|
-
|
|
198
|
-
|
|
211
|
+
} else if (current <= 4) {
|
|
212
|
+
// Near start: [1, 2, 3, 4, 5] [ellipsis] [last]
|
|
213
|
+
for (let i = 1; i <= 5; i++) {
|
|
214
|
+
items.push({ type: "page", value: i });
|
|
215
|
+
}
|
|
216
|
+
items.push({ type: "ellipsis" });
|
|
217
|
+
items.push({ type: "page", value: total });
|
|
218
|
+
} else if (current >= total - 3) {
|
|
219
|
+
// Near end: [1] [ellipsis] [last-4, last-3, last-2, last-1, last]
|
|
220
|
+
items.push({ type: "page", value: 1 });
|
|
221
|
+
items.push({ type: "ellipsis" });
|
|
222
|
+
for (let i = total - 4; i <= total; i++) {
|
|
223
|
+
items.push({ type: "page", value: i });
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
// Middle: [1] [ellipsis] [current-1, current, current+1] [ellipsis] [last]
|
|
227
|
+
items.push({ type: "page", value: 1 });
|
|
228
|
+
items.push({ type: "ellipsis" });
|
|
229
|
+
items.push({ type: "page", value: current - 1 });
|
|
230
|
+
items.push({ type: "page", value: current });
|
|
231
|
+
items.push({ type: "page", value: current + 1 });
|
|
232
|
+
items.push({ type: "ellipsis" });
|
|
233
|
+
items.push({ type: "page", value: total });
|
|
234
|
+
}
|
|
199
235
|
|
|
200
236
|
items.push({ type: "next" });
|
|
201
237
|
|
|
@@ -222,6 +258,11 @@ export class RelPagination extends LitElement {
|
|
|
222
258
|
);
|
|
223
259
|
}
|
|
224
260
|
|
|
261
|
+
private getHref(page: number): string {
|
|
262
|
+
if (!this.hrefTemplate) return "#";
|
|
263
|
+
return this.hrefTemplate.replace(/\{page\}/, String(page));
|
|
264
|
+
}
|
|
265
|
+
|
|
225
266
|
private handleKeyDown(event: KeyboardEvent, callback: () => void) {
|
|
226
267
|
if (event.key === "Enter" || event.key === " ") {
|
|
227
268
|
event.preventDefault();
|
|
@@ -249,6 +290,10 @@ export class RelPagination extends LitElement {
|
|
|
249
290
|
const current = this.activePage;
|
|
250
291
|
const useLinks = !!this.hrefTemplate;
|
|
251
292
|
|
|
293
|
+
if (item.type === "spacer") {
|
|
294
|
+
return html`<span class="pagination-spacer"></span>`;
|
|
295
|
+
}
|
|
296
|
+
|
|
252
297
|
if (item.type === "ellipsis") {
|
|
253
298
|
return html`<span class="ellipsis">…</span>`;
|
|
254
299
|
}
|
|
@@ -258,10 +303,11 @@ export class RelPagination extends LitElement {
|
|
|
258
303
|
const targetPage = current - 1;
|
|
259
304
|
|
|
260
305
|
if (useLinks) {
|
|
261
|
-
const href = disabled ? "#" : this.
|
|
306
|
+
const href = disabled ? "#" : this.getHref(targetPage);
|
|
262
307
|
return html`
|
|
263
308
|
<a
|
|
264
309
|
href="${href}"
|
|
310
|
+
class="prev-btn"
|
|
265
311
|
aria-label="Go to previous page"
|
|
266
312
|
aria-disabled="${disabled}"
|
|
267
313
|
@click="${(e: Event) => {
|
|
@@ -281,6 +327,7 @@ export class RelPagination extends LitElement {
|
|
|
281
327
|
return html`
|
|
282
328
|
<button
|
|
283
329
|
type="button"
|
|
330
|
+
class="prev-btn"
|
|
284
331
|
aria-label="Go to previous page"
|
|
285
332
|
?disabled="${disabled}"
|
|
286
333
|
@click="${() => this.handlePageChange(targetPage)}"
|
|
@@ -295,10 +342,11 @@ export class RelPagination extends LitElement {
|
|
|
295
342
|
const targetPage = current + 1;
|
|
296
343
|
|
|
297
344
|
if (useLinks) {
|
|
298
|
-
const href = disabled ? "#" : this.
|
|
345
|
+
const href = disabled ? "#" : this.getHref(targetPage);
|
|
299
346
|
return html`
|
|
300
347
|
<a
|
|
301
348
|
href="${href}"
|
|
349
|
+
class="next-btn"
|
|
302
350
|
aria-label="Go to next page"
|
|
303
351
|
aria-disabled="${disabled}"
|
|
304
352
|
@click="${(e: Event) => {
|
|
@@ -318,6 +366,7 @@ export class RelPagination extends LitElement {
|
|
|
318
366
|
return html`
|
|
319
367
|
<button
|
|
320
368
|
type="button"
|
|
369
|
+
class="next-btn"
|
|
321
370
|
aria-label="Go to next page"
|
|
322
371
|
?disabled="${disabled}"
|
|
323
372
|
@click="${() => this.handlePageChange(targetPage)}"
|
|
@@ -332,7 +381,7 @@ export class RelPagination extends LitElement {
|
|
|
332
381
|
const isCurrent = pageNum === current;
|
|
333
382
|
|
|
334
383
|
if (useLinks) {
|
|
335
|
-
const href = this.
|
|
384
|
+
const href = this.getHref(pageNum);
|
|
336
385
|
return html`
|
|
337
386
|
<a
|
|
338
387
|
href="${href}"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
import "../../styles/vars-v2.css";
|
|
3
4
|
|
|
4
5
|
@customElement("rel-popover-content")
|
|
5
6
|
export class RelPopoverContent extends LitElement {
|
|
@@ -13,14 +14,14 @@ export class RelPopoverContent extends LitElement {
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
.popover-content {
|
|
16
|
-
background: var(--rel-
|
|
17
|
-
border: var(--rel-borders-width-stroke-100) solid var(--rel-
|
|
17
|
+
background: var(--rel-color-bg-primary);
|
|
18
|
+
border: var(--rel-borders-width-stroke-100) solid var(--rel-color-border-default);
|
|
18
19
|
border-radius: var(--rel-borders-radius-border-radius-200);
|
|
19
20
|
box-shadow: var(--rel-shadows-shadow-300);
|
|
20
21
|
padding: var(--rel-spacing-space-md);
|
|
21
22
|
font-family: var(--rel-fontFamilies-primary);
|
|
22
23
|
font-size: var(--rel-fontSizes-sm);
|
|
23
|
-
color: var(--rel-
|
|
24
|
+
color: var(--rel-color-text-heading);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
.popover-content ::slotted(h1),
|
|
@@ -31,12 +32,12 @@ export class RelPopoverContent extends LitElement {
|
|
|
31
32
|
.popover-content ::slotted(h6) {
|
|
32
33
|
margin: 0 0 var(--rel-spacing-space-xs);
|
|
33
34
|
font-weight: var(--rel-fontWeights-semibold);
|
|
34
|
-
color: var(--rel-
|
|
35
|
+
color: var(--rel-color-text-heading);
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
.popover-content ::slotted(p) {
|
|
38
39
|
margin: 0 0 var(--rel-spacing-space-sm);
|
|
39
|
-
color: var(--rel-
|
|
40
|
+
color: var(--rel-color-text-placeholder);
|
|
40
41
|
line-height: var(--rel-lineHeights-md);
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, css } from "lit";
|
|
2
2
|
import { customElement, property, state, query } from "lit/decorators.js";
|
|
3
|
+
import "../../styles/vars-v2.css";
|
|
3
4
|
|
|
4
5
|
type SideType = "top" | "right" | "bottom" | "left";
|
|
5
6
|
type AlignType = "start" | "center" | "end";
|
|
@@ -35,6 +36,7 @@ export class RelPopover extends LitElement {
|
|
|
35
36
|
|
|
36
37
|
private triggerEl: HTMLElement | null = null;
|
|
37
38
|
private returnFocusEl: HTMLElement | null = null;
|
|
39
|
+
private uniqueId = `popover-${Math.random().toString(36).slice(2)}`;
|
|
38
40
|
|
|
39
41
|
/* =======================
|
|
40
42
|
* STYLES
|
|
@@ -47,8 +49,12 @@ export class RelPopover extends LitElement {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
:host([disabled]) {
|
|
50
|
-
pointer-events: none;
|
|
51
52
|
opacity: 0.6;
|
|
53
|
+
cursor: not-allowed;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
:host([disabled]) * {
|
|
57
|
+
pointer-events: none;
|
|
52
58
|
}
|
|
53
59
|
|
|
54
60
|
.content-wrapper {
|
|
@@ -81,10 +87,8 @@ export class RelPopover extends LitElement {
|
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
firstUpdated() {
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
'[slot="trigger"]',
|
|
87
|
-
) as HTMLElement | null;
|
|
90
|
+
// triggerEl is resolved via onTriggerSlotChange; call aria in case slot
|
|
91
|
+
// content was already assigned before firstUpdated
|
|
88
92
|
this.applyTriggerAria();
|
|
89
93
|
}
|
|
90
94
|
|
|
@@ -134,18 +138,13 @@ export class RelPopover extends LitElement {
|
|
|
134
138
|
|
|
135
139
|
const path = e.composedPath();
|
|
136
140
|
|
|
137
|
-
// Toggle ONLY if pointerdown originated from trigger
|
|
138
|
-
|
|
139
|
-
(n) => n instanceof HTMLElement && n.getAttribute?.("slot") === "trigger",
|
|
140
|
-
) as HTMLElement | undefined;
|
|
141
|
-
|
|
142
|
-
if (!triggerNode) return;
|
|
141
|
+
// Toggle ONLY if pointerdown originated from the trigger element
|
|
142
|
+
if (!this.triggerEl || !path.includes(this.triggerEl)) return;
|
|
143
143
|
|
|
144
144
|
// Prevent this interaction from becoming an "outside click"
|
|
145
145
|
e.preventDefault();
|
|
146
146
|
e.stopPropagation();
|
|
147
147
|
|
|
148
|
-
this.triggerEl = triggerNode;
|
|
149
148
|
this.setOpen(!this.activeOpen);
|
|
150
149
|
};
|
|
151
150
|
|
|
@@ -239,7 +238,8 @@ export class RelPopover extends LitElement {
|
|
|
239
238
|
}
|
|
240
239
|
|
|
241
240
|
private restoreFocus() {
|
|
242
|
-
this.triggerEl?.focus();
|
|
241
|
+
(this.returnFocusEl ?? this.triggerEl)?.focus();
|
|
242
|
+
this.returnFocusEl = null;
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
private trapFocusLoop(e: KeyboardEvent) {
|
|
@@ -278,12 +278,25 @@ export class RelPopover extends LitElement {
|
|
|
278
278
|
const t = this.triggerEl.getBoundingClientRect();
|
|
279
279
|
const c = this.contentWrapper.getBoundingClientRect();
|
|
280
280
|
|
|
281
|
-
let top =
|
|
282
|
-
let left =
|
|
281
|
+
let top = 0;
|
|
282
|
+
let left = 0;
|
|
283
283
|
|
|
284
|
-
if (this.side === "top")
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
if (this.side === "top") {
|
|
285
|
+
top = t.top - c.height - this.sideOffset;
|
|
286
|
+
left = t.left + t.width / 2 - c.width / 2;
|
|
287
|
+
}
|
|
288
|
+
if (this.side === "bottom") {
|
|
289
|
+
top = t.bottom + this.sideOffset;
|
|
290
|
+
left = t.left + t.width / 2 - c.width / 2;
|
|
291
|
+
}
|
|
292
|
+
if (this.side === "left") {
|
|
293
|
+
top = t.top + t.height / 2 - c.height / 2;
|
|
294
|
+
left = t.left - c.width - this.sideOffset;
|
|
295
|
+
}
|
|
296
|
+
if (this.side === "right") {
|
|
297
|
+
top = t.top + t.height / 2 - c.height / 2;
|
|
298
|
+
left = t.right + this.sideOffset;
|
|
299
|
+
}
|
|
287
300
|
|
|
288
301
|
top = Math.max(8, Math.min(top, window.innerHeight - c.height - 8));
|
|
289
302
|
left = Math.max(8, Math.min(left, window.innerWidth - c.width - 8));
|
|
@@ -295,10 +308,18 @@ export class RelPopover extends LitElement {
|
|
|
295
308
|
* ARIA
|
|
296
309
|
* ======================= */
|
|
297
310
|
|
|
311
|
+
private onTriggerSlotChange(e: Event) {
|
|
312
|
+
const slot = e.target as HTMLSlotElement;
|
|
313
|
+
const first = slot.assignedElements({ flatten: true })[0] as HTMLElement | undefined;
|
|
314
|
+
this.triggerEl = first ?? null;
|
|
315
|
+
this.applyTriggerAria();
|
|
316
|
+
}
|
|
317
|
+
|
|
298
318
|
private applyTriggerAria() {
|
|
299
319
|
if (!this.triggerEl) return;
|
|
300
320
|
this.triggerEl.setAttribute("aria-haspopup", "dialog");
|
|
301
321
|
this.triggerEl.setAttribute("aria-expanded", String(this.activeOpen));
|
|
322
|
+
this.triggerEl.setAttribute("aria-controls", this.uniqueId);
|
|
302
323
|
}
|
|
303
324
|
|
|
304
325
|
/* =======================
|
|
@@ -307,14 +328,15 @@ export class RelPopover extends LitElement {
|
|
|
307
328
|
|
|
308
329
|
render() {
|
|
309
330
|
return html`
|
|
310
|
-
<slot
|
|
331
|
+
<slot @slotchange=${this.onTriggerSlotChange}></slot>
|
|
311
332
|
|
|
312
333
|
<div
|
|
334
|
+
id="${this.uniqueId}"
|
|
313
335
|
class="content-wrapper"
|
|
314
336
|
style="${this.contentStyle}"
|
|
315
337
|
?open="${this.activeOpen}"
|
|
316
338
|
>
|
|
317
|
-
<slot></slot>
|
|
339
|
+
<slot name="content"></slot>
|
|
318
340
|
</div>
|
|
319
341
|
`;
|
|
320
342
|
}
|