@reliability-design/web 1.0.6 → 1.1.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 (60) hide show
  1. package/dist/components/rel-accordion/rel-accordion.ts +4 -0
  2. package/dist/components/rel-alert/rel-alert.ts +83 -13
  3. package/dist/components/rel-avatar/rel-avatar.ts +3 -2
  4. package/dist/components/rel-badge/rel-badge.ts +6 -2
  5. package/dist/components/rel-button/rel-button.ts +64 -8
  6. package/dist/components/rel-calendar/rel-calendar.ts +3 -3
  7. package/dist/components/rel-carousel/rel-carousel.ts +10 -11
  8. package/dist/components/rel-checkbox/rel-checkbox.ts +33 -2
  9. package/dist/components/rel-chip/rel-chip.ts +63 -5
  10. package/dist/components/rel-divider/rel-divider.ts +9 -0
  11. package/dist/components/rel-drawer/rel-drawer-footer.ts +29 -0
  12. package/dist/components/rel-drawer/rel-drawer.ts +17 -26
  13. package/dist/components/rel-menu/rel-menu.ts +53 -21
  14. package/dist/components/rel-menubar/rel-menubar.ts +52 -23
  15. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +240 -143
  16. package/dist/components/rel-nav-menu/rel-nav-menu.ts +227 -331
  17. package/dist/components/rel-navbar/rel-navbar.ts +13 -0
  18. package/dist/components/rel-pagination/rel-pagination.ts +11 -6
  19. package/dist/components/rel-popover/rel-popover.ts +16 -13
  20. package/dist/components/rel-radio/rel-radio.ts +18 -1
  21. package/dist/components/rel-resizable/rel-resizable-handle.ts +4 -8
  22. package/dist/components/rel-select/rel-select.ts +14 -0
  23. package/dist/components/rel-sheet/rel-sheet.ts +7 -6
  24. package/dist/components/rel-sidebar/rel-sidebar.ts +13 -5
  25. package/dist/components/rel-slider/rel-slider.ts +25 -2
  26. package/dist/components/rel-snackbar/rel-snackbar.ts +46 -16
  27. package/dist/components/rel-stepper/rel-stepper.ts +32 -21
  28. package/dist/components/rel-switch/rel-switch.ts +19 -6
  29. package/dist/components/rel-tab/rel-tab.ts +49 -15
  30. package/dist/components/rel-table/rel-table-body.ts +5 -0
  31. package/dist/components/rel-table/rel-table-caption.ts +6 -1
  32. package/dist/components/rel-table/rel-table-cell.ts +42 -49
  33. package/dist/components/rel-table/rel-table-footer.ts +5 -0
  34. package/dist/components/rel-table/rel-table-head.ts +13 -1
  35. package/dist/components/rel-table/rel-table-header.ts +5 -0
  36. package/dist/components/rel-table/rel-table-row.ts +7 -3
  37. package/dist/components/rel-table/rel-table.ts +8 -2
  38. package/dist/components/rel-textfield/rel-textfield.ts +20 -20
  39. package/dist/components/rel-toast/rel-toast.ts +31 -10
  40. package/dist/components/rel-tooltip/rel-tooltip.ts +123 -80
  41. package/dist/components/rel-topbar/rel-topbar-actions.ts +23 -0
  42. package/dist/components/rel-topbar/rel-topbar-brand.ts +46 -0
  43. package/dist/components/rel-topbar/rel-topbar-dropdown-item.ts +33 -0
  44. package/dist/components/rel-topbar/rel-topbar-dropdown.ts +28 -0
  45. package/dist/components/rel-topbar/rel-topbar-item.ts +315 -0
  46. package/dist/components/rel-topbar/rel-topbar-mobile-panel.ts +23 -0
  47. package/dist/components/rel-topbar/rel-topbar-profile.ts +248 -0
  48. package/dist/components/rel-topbar/rel-topbar-utilities.ts +23 -0
  49. package/dist/components/rel-topbar/rel-topbar.ts +329 -0
  50. package/dist/index.d.mts +278 -289
  51. package/dist/index.d.ts +278 -289
  52. package/dist/index.js +4498 -5727
  53. package/dist/index.js.map +1 -1
  54. package/dist/index.mjs +4535 -5756
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/styles/vars.css +346 -294
  57. package/dist/{vars-ITL2K3KO.css → vars-TBB4BMSD.css} +346 -294
  58. package/package.json +2 -1
  59. package/dist/components/rel-quote-page/README.md +0 -166
  60. package/dist/components/rel-quote-page/rel-quote-page.ts +0 -816
@@ -1,143 +1,240 @@
1
- import { LitElement, html, css } from "lit";
2
- import { customElement, property, state } from "lit/decorators.js";
3
-
4
- @customElement("rel-nav-menu-item")
5
- export class RelNavMenuItem extends LitElement {
6
- @property({ type: String }) label = "";
7
- @property({ type: String }) href = "";
8
- @property({ type: String, attribute: "item-id" }) itemId = "";
9
- @property({ type: Boolean, reflect: true }) disabled = false;
10
- @property({ type: String }) icon = "";
11
-
12
- @state() private hasContent = false;
13
-
14
- static styles = css`
15
- :host {
16
- display: inline-block;
17
- }
18
-
19
- .trigger {
20
- display: inline-flex;
21
- align-items: center;
22
- gap: var(--rel-spacing-space-2xs);
23
- padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-md);
24
- font-family: var(--rel-fontFamilies-primary);
25
- font-size: var(--rel-fontSizes-sm);
26
- font-weight: var(--rel-fontWeights-medium);
27
- color: var(--rel-colors-gray-heading);
28
- background: transparent;
29
- border: none;
30
- border-radius: var(--rel-borders-radius-border-radius-200);
31
- cursor: pointer;
32
- transition: all 0.15s ease;
33
- text-decoration: none;
34
- outline: none;
35
- user-select: none;
36
- }
37
-
38
- .trigger:hover:not(:disabled) {
39
- background: var(--rel-surface-secondary, #fafafa);
40
- }
41
-
42
- .trigger:focus-visible {
43
- outline: 2px solid var(--rel-colors-blue-primary);
44
- outline-offset: 2px;
45
- }
46
-
47
- .trigger.active {
48
- background: var(--rel-surface-secondary, #fafafa);
49
- }
50
-
51
- .trigger:disabled {
52
- opacity: 0.5;
53
- cursor: not-allowed;
54
- }
55
-
56
- :host([disabled]) .trigger {
57
- opacity: 0.5;
58
- cursor: not-allowed;
59
- }
60
-
61
- .content {
62
- display: none;
63
- }
64
- `;
65
-
66
- connectedCallback() {
67
- super.connectedCallback();
68
- // Generate item-id from label if not provided
69
- if (!this.itemId && this.label) {
70
- this.itemId = this.label.toLowerCase().replace(/\s+/g, "-");
71
- }
72
- }
73
-
74
- firstUpdated() {
75
- // Check if there's any slotted content
76
- const slot = this.shadowRoot?.querySelector("slot");
77
- if (slot) {
78
- const nodes = slot.assignedNodes({ flatten: true });
79
- this.hasContent = nodes.some(
80
- (node) => node.nodeType === Node.ELEMENT_NODE || node.textContent?.trim()
81
- );
82
- }
83
- }
84
-
85
- private handleSlotChange() {
86
- const slot = this.shadowRoot?.querySelector("slot");
87
- if (slot) {
88
- const nodes = slot.assignedNodes({ flatten: true });
89
- this.hasContent = nodes.some(
90
- (node) => node.nodeType === Node.ELEMENT_NODE || node.textContent?.trim()
91
- );
92
- }
93
- }
94
-
95
- get triggerId() {
96
- return `nav-trigger-${this.itemId}`;
97
- }
98
-
99
- get panelId() {
100
- return `nav-panel-${this.itemId}`;
101
- }
102
-
103
- render() {
104
- const isLink = !!this.href && !this.hasContent;
105
- const tagName = isLink ? "a" : "button";
106
- const attrs = isLink
107
- ? { href: this.href }
108
- : {
109
- type: "button",
110
- "aria-haspopup": this.hasContent ? "menu" : undefined,
111
- "aria-controls": this.hasContent ? this.panelId : undefined,
112
- };
113
-
114
- return html`
115
- ${isLink
116
- ? html`
117
- <a
118
- class="trigger"
119
- href="${this.href}"
120
- id="${this.triggerId}"
121
- ?disabled="${this.disabled}"
122
- >
123
- ${this.label}
124
- </a>
125
- `
126
- : html`
127
- <button
128
- class="trigger"
129
- id="${this.triggerId}"
130
- type="button"
131
- ?disabled="${this.disabled}"
132
- aria-haspopup="${this.hasContent ? "menu" : "false"}"
133
- aria-controls="${this.hasContent ? this.panelId : ""}"
134
- >
135
- ${this.label}
136
- </button>
137
- `}
138
- <div class="content">
139
- <slot @slotchange="${this.handleSlotChange}"></slot>
140
- </div>
141
- `;
142
- }
143
- }
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("rel-nav-menu-item")
5
+ export class RelNavMenuItem extends LitElement {
6
+ @property({ type: String }) label = "";
7
+ @property({ type: String }) href = "";
8
+ @property({ type: String, attribute: "item-id" }) itemId = "";
9
+ @property({ type: Boolean, reflect: true }) disabled = false;
10
+ @property({ type: String }) icon = "";
11
+
12
+ /** Promoted from @state so rel-nav-menu can read it as a property. */
13
+ @property({ type: Boolean, reflect: true }) hasContent = false;
14
+
15
+ /** Set by rel-nav-menu to open/close this item's panel. */
16
+ @property({ type: Boolean, reflect: true }) open = false;
17
+
18
+ static styles = css`
19
+ :host {
20
+ display: inline-block;
21
+ }
22
+
23
+ .trigger {
24
+ display: inline-flex;
25
+ align-items: center;
26
+ gap: var(--rel-spacing-space-2xs);
27
+ padding: var(--rel-spacing-space-xs) var(--rel-spacing-space-md);
28
+ font-family: var(--rel-fontFamilies-primary);
29
+ font-size: var(--rel-fontSizes-sm);
30
+ font-weight: var(--rel-fontWeights-medium);
31
+ color: var(--rel-colors-gray-heading);
32
+ background: transparent;
33
+ border: none;
34
+ border-radius: var(--rel-borders-radius-border-radius-200);
35
+ cursor: pointer;
36
+ transition: all 0.15s ease;
37
+ text-decoration: none;
38
+ outline: none;
39
+ user-select: none;
40
+ }
41
+
42
+ .trigger:hover:not(:disabled) {
43
+ background: var(--rel-surface-secondary, #fafafa);
44
+ }
45
+
46
+ .trigger:focus-visible {
47
+ outline: 2px solid var(--rel-colors-blue-primary);
48
+ outline-offset: 2px;
49
+ }
50
+
51
+ /* Active state driven by :host([open]) — no external class manipulation needed */
52
+ :host([open]) .trigger,
53
+ .trigger.active {
54
+ background: var(--rel-surface-secondary, #fafafa);
55
+ }
56
+
57
+ .trigger:disabled {
58
+ opacity: 0.5;
59
+ cursor: not-allowed;
60
+ }
61
+
62
+ :host([disabled]) .trigger {
63
+ opacity: 0.5;
64
+ cursor: not-allowed;
65
+ }
66
+
67
+ /* Panel lives inside the item's own shadow DOM */
68
+ .panel {
69
+ position: fixed;
70
+ min-width: 320px;
71
+ max-width: 600px;
72
+ background: var(--rel-colors-white);
73
+ border: var(--rel-borders-width-stroke-100) solid var(--rel-colors-gray-border);
74
+ border-radius: var(--rel-borders-radius-border-radius-200);
75
+ box-shadow: var(--rel-shadows-shadow-300);
76
+ padding: var(--rel-spacing-space-xs);
77
+ z-index: 1000;
78
+ display: none;
79
+ }
80
+
81
+ .panel.open {
82
+ display: block;
83
+ }
84
+ `;
85
+
86
+ connectedCallback() {
87
+ super.connectedCallback();
88
+ if (!this.itemId && this.label) {
89
+ this.itemId = this.label.toLowerCase().replace(/\s+/g, "-");
90
+ }
91
+ }
92
+
93
+ firstUpdated() {
94
+ this.updateHasContent();
95
+ }
96
+
97
+ updated(changed: Map<string, any>) {
98
+ if (changed.has("open") && this.open) {
99
+ // Wait for paint so the panel has layout dimensions before positioning.
100
+ this.updateComplete.then(() => this.positionPanel());
101
+ }
102
+ }
103
+
104
+ // ── Content detection ──────────────────────────────────────────────────────
105
+
106
+ private updateHasContent() {
107
+ const slot = this.shadowRoot?.querySelector("slot");
108
+ if (slot) {
109
+ const nodes = slot.assignedNodes({ flatten: true });
110
+ this.hasContent = nodes.some(
111
+ (node) => node.nodeType === Node.ELEMENT_NODE || node.textContent?.trim()
112
+ );
113
+ }
114
+ }
115
+
116
+ private handleSlotChange() {
117
+ this.updateHasContent();
118
+ }
119
+
120
+ // ── Panel positioning (moved from rel-nav-menu) ────────────────────────────
121
+
122
+ private positionPanel() {
123
+ const trigger = this.shadowRoot?.querySelector(".trigger") as HTMLElement;
124
+ const panel = this.shadowRoot?.querySelector(".panel") as HTMLElement;
125
+ if (!trigger || !panel) return;
126
+
127
+ const triggerRect = trigger.getBoundingClientRect();
128
+ const panelRect = panel.getBoundingClientRect();
129
+ const viewportWidth = window.innerWidth;
130
+ const viewportHeight = window.innerHeight;
131
+
132
+ let top = triggerRect.bottom + 8;
133
+ let left = triggerRect.left;
134
+
135
+ // Handle right overflow
136
+ if (left + panelRect.width > viewportWidth) {
137
+ left = viewportWidth - panelRect.width - 16;
138
+ }
139
+
140
+ // Handle left overflow
141
+ if (left < 0) left = 16;
142
+
143
+ // Handle bottom overflow — flip above if more space
144
+ if (top + panelRect.height > viewportHeight) {
145
+ const spaceAbove = triggerRect.top;
146
+ const spaceBelow = viewportHeight - triggerRect.bottom;
147
+ if (spaceAbove > spaceBelow && spaceAbove > panelRect.height) {
148
+ top = triggerRect.top - panelRect.height - 8;
149
+ }
150
+ }
151
+
152
+ panel.style.top = `${top}px`;
153
+ panel.style.left = `${left}px`;
154
+ }
155
+
156
+ // ── Events dispatched upward — rel-nav-menu listens via connectedCallback ──
157
+
158
+ private handleTriggerClick() {
159
+ if (this.disabled) return;
160
+ this.dispatchEvent(
161
+ new CustomEvent("rel-nav-item-click", {
162
+ detail: { itemId: this.itemId, hasContent: this.hasContent },
163
+ bubbles: true,
164
+ composed: true,
165
+ })
166
+ );
167
+ }
168
+
169
+ private handleTriggerMouseEnter() {
170
+ if (this.disabled) return;
171
+ this.dispatchEvent(
172
+ new CustomEvent("rel-nav-item-hover", {
173
+ detail: { itemId: this.itemId },
174
+ bubbles: true,
175
+ composed: true,
176
+ })
177
+ );
178
+ }
179
+
180
+ // ── ID helpers ─────────────────────────────────────────────────────────────
181
+
182
+ get triggerId() {
183
+ return `nav-trigger-${this.itemId}`;
184
+ }
185
+
186
+ get panelId() {
187
+ return `nav-panel-${this.itemId}`;
188
+ }
189
+
190
+ // ── Render ─────────────────────────────────────────────────────────────────
191
+
192
+ render() {
193
+ const isLink = !!this.href && !this.hasContent;
194
+
195
+ return html`
196
+ ${isLink
197
+ ? html`
198
+ <a
199
+ class="trigger"
200
+ href="${this.href}"
201
+ id="${this.triggerId}"
202
+ ?disabled="${this.disabled}"
203
+ @click="${this.handleTriggerClick}"
204
+ @mouseenter="${this.handleTriggerMouseEnter}"
205
+ >
206
+ ${this.label}
207
+ </a>
208
+ `
209
+ : html`
210
+ <button
211
+ class="trigger"
212
+ id="${this.triggerId}"
213
+ type="button"
214
+ ?disabled="${this.disabled}"
215
+ aria-haspopup="${this.hasContent ? "menu" : "false"}"
216
+ aria-controls="${this.hasContent ? this.panelId : ""}"
217
+ aria-expanded="${this.open ? "true" : "false"}"
218
+ @click="${this.handleTriggerClick}"
219
+ @mouseenter="${this.handleTriggerMouseEnter}"
220
+ >
221
+ ${this.label}
222
+ </button>
223
+ `}
224
+
225
+ <!--
226
+ Panel rendered inside this shadow root.
227
+ Slot projects the consumer's light-DOM children directly — no cloning.
228
+ rel-nav-menu sets item.open = true/false to show/hide.
229
+ -->
230
+ <div
231
+ class="panel ${this.open ? "open" : ""}"
232
+ id="${this.panelId}"
233
+ role="menu"
234
+ @click="${(e: Event) => e.stopPropagation()}"
235
+ >
236
+ <slot @slotchange="${this.handleSlotChange}"></slot>
237
+ </div>
238
+ `;
239
+ }
240
+ }