@ctrliq/quantic-components 1.67.2 → 1.67.4

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.
@@ -5,10 +5,9 @@ export declare class InlineEdit extends QuanticElement {
5
5
  label: string;
6
6
  active: boolean;
7
7
  invalid: boolean;
8
- private hasLabelSlot;
9
8
  connectedCallback(): void;
10
9
  disconnectedCallback(): void;
11
- static styles: import("lit").CSSResult;
10
+ static styles: import("lit").CSSResult[];
12
11
  private activate;
13
12
  private deactivate;
14
13
  private handleActivateClick;
@@ -5,9 +5,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { css, html } from 'lit';
8
- import { state } from 'lit/decorators.js';
9
8
  import { quanticElement, QuanticElement } from '../shared/quantic-element';
10
- import { onSlotChange } from '../shared/slot-utils';
9
+ import { whenSlotPresent } from '../shared/slot-utils';
11
10
  import { IconSize } from '../icon/index.constants';
12
11
  import { LucideIconPencil } from '../icon/__generated__/lucide/pencil';
13
12
  import { classMap } from 'lit/directives/class-map.js';
@@ -19,7 +18,6 @@ let InlineEdit = class InlineEdit extends QuanticElement {
19
18
  this.label = '';
20
19
  this.active = false;
21
20
  this.invalid = false;
22
- this.hasLabelSlot = false;
23
21
  this.handleActivateClick = () => {
24
22
  if (!this.active)
25
23
  this.activate();
@@ -77,7 +75,7 @@ let InlineEdit = class InlineEdit extends QuanticElement {
77
75
  }
78
76
  }
79
77
  render() {
80
- const hasLabel = this.hasLabelSlot || !!this.label;
78
+ const hasLabel = !!this.label;
81
79
  return html `
82
80
  <div
83
81
  class="${classMap({
@@ -90,7 +88,7 @@ let InlineEdit = class InlineEdit extends QuanticElement {
90
88
  @keydown=${this.handleTriggerKey}
91
89
  >
92
90
  <span class=${classMap({ label: true, 'is-empty': !hasLabel })}
93
- ><slot name="label" @slotchange=${onSlotChange((has) => (this.hasLabelSlot = has))}>${this.label}</slot></span
91
+ ><slot name="label">${this.label}</slot></span
94
92
  >
95
93
  <span class="value">
96
94
  <span class="display">
@@ -120,7 +118,7 @@ InlineEdit.meta = {
120
118
  editor: { description: 'Input element shown when the field is active.' },
121
119
  },
122
120
  };
123
- InlineEdit.styles = css `
121
+ InlineEdit.styles = [css `
124
122
  :host {
125
123
  display: block;
126
124
  padding: var(
@@ -164,7 +162,6 @@ InlineEdit.styles = css `
164
162
  );
165
163
  }
166
164
 
167
- /* The label renders unconditionally so its slot exists to fire slotchange. */
168
165
  .label.is-empty {
169
166
  display: none;
170
167
  }
@@ -234,7 +231,13 @@ InlineEdit.styles = css `
234
231
  .is-active .editor {
235
232
  display: block;
236
233
  }
237
- `;
234
+ `,
235
+ whenSlotPresent('label', css `
236
+ .label.is-empty {
237
+ display: revert;
238
+ }
239
+ `),
240
+ ];
238
241
  __decorate([
239
242
  prop({ type: 'string', default: '', description: 'Fallback label text when no label slot content is provided.' })
240
243
  ], InlineEdit.prototype, "label", void 0);
@@ -244,9 +247,6 @@ __decorate([
244
247
  __decorate([
245
248
  prop({ type: 'boolean', default: 'false', description: 'When true, focusout does not close the editor. The editor stays open until the value is valid or the user cancels.' })
246
249
  ], InlineEdit.prototype, "invalid", void 0);
247
- __decorate([
248
- state()
249
- ], InlineEdit.prototype, "hasLabelSlot", void 0);
250
250
  InlineEdit = __decorate([
251
251
  event('cancel', { description: 'Fired on Escape. Consumer should revert optimistic state.' }),
252
252
  quanticElement('quantic-inline-edit')
@@ -258,18 +258,28 @@ export const SidebarWithStickyHeader = story().render(({ html }) => html `
258
258
  slot="header"
259
259
  style="display: flex; align-items: center; gap: var(--quantic-spacing-2); padding: var(--quantic-spacing-2); border-bottom: 1px solid var(--quantic-border-secondary); margin-bottom: var(--quantic-spacing-2);"
260
260
  >
261
- <quantic-icon-brand-fuzzball-solid size="sm"></quantic-icon-brand-fuzzball-solid>
262
- <span style="font-weight: var(--quantic-font-weight-semibold); font-size: var(--quantic-font-size-sm);">CIQ Engineering</span>
261
+ <quantic-icon-brand-fuzzball-solid
262
+ size="sm"
263
+ ></quantic-icon-brand-fuzzball-solid>
264
+ <span
265
+ style="font-weight: var(--quantic-font-weight-semibold); font-size: var(--quantic-font-size-sm);"
266
+ >CIQ Engineering</span
267
+ >
263
268
  </div>
264
269
  ${Array.from({ length: 20 }, (_, i) => html `
265
270
  <quantic-sidebar-menu-item href="#" label="Nav item ${i + 1}">
266
- <quantic-icon-lucide-circle slot="icon" size="sm"></quantic-icon-lucide-circle>
271
+ <quantic-icon-lucide-circle
272
+ slot="icon"
273
+ size="sm"
274
+ ></quantic-icon-lucide-circle>
267
275
  </quantic-sidebar-menu-item>
268
276
  `)}
269
277
  </quantic-sidebar>
270
278
  <quantic-page slot="body">
271
279
  <quantic-panel variant="solid">
272
- <quantic-panel-header slot="header">Sticky sidebar header</quantic-panel-header>
280
+ <quantic-panel-header slot="header"
281
+ >Sticky sidebar header</quantic-panel-header
282
+ >
273
283
  Scroll the sidebar — the header above the nav items stays fixed.
274
284
  </quantic-panel>
275
285
  </quantic-page>
@@ -1,4 +1,4 @@
1
- import { type PropertyValues } from 'lit';
1
+ import { type CSSResultGroup, type PropertyValues } from 'lit';
2
2
  import { LayoutVariant } from './index.constants';
3
3
  import { QuanticElement } from '../shared/quantic-element';
4
4
  import type { ComponentMeta } from '../shared/meta.types';
@@ -10,8 +10,6 @@ export declare class Layout extends Layout_base {
10
10
  private previousIsSmallViewport?;
11
11
  private hasSidebarSlot;
12
12
  private hasTitlebarSlot;
13
- private hasNavbarSlot;
14
- private hasLogoSlot;
15
13
  private asideElement?;
16
14
  private toggleButtonElement?;
17
15
  private focusTrap?;
@@ -28,10 +26,10 @@ export declare class Layout extends Layout_base {
28
26
  protected willUpdate(_props: PropertyValues): void;
29
27
  protected updated(props: PropertyValues): void;
30
28
  static styles: import("lit").CSSResult;
29
+ static finalizeStyles(styles?: CSSResultGroup): import("lit").CSSResultOrNative[];
31
30
  private get isAsideCollapsible();
32
31
  private get hasSidebar();
33
32
  private get hasTitlebar();
34
- private get hasHeader();
35
33
  render(): import("lit").TemplateResult;
36
34
  }
37
35
  export {};
@@ -4,13 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { css } from 'lit';
7
+ import { css, unsafeCSS } from 'lit';
8
8
  import { query, state } from 'lit/decorators.js';
9
9
  import { html } from 'lit/static-html.js';
10
10
  import { classMap } from 'lit/directives/class-map.js';
11
11
  import { provide } from '@lit/context';
12
12
  import { AutoHideEmptySlotsMixin } from '../shared/auto-hide-empty-slots.mixin';
13
- import { onSlotChange } from '../shared/slot-utils';
13
+ import { onSlotChange, whenSlotPresent } from '../shared/slot-utils';
14
14
  import { respond, Breakpoint } from '../shared/respond.decorator';
15
15
  import { LayoutVariant } from './index.constants';
16
16
  import { asideExpandedContext } from './index.context';
@@ -27,8 +27,6 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
27
27
  this.variant = LayoutVariant.Default;
28
28
  this.hasSidebarSlot = false;
29
29
  this.hasTitlebarSlot = false;
30
- this.hasNavbarSlot = false;
31
- this.hasLogoSlot = false;
32
30
  this._isAsideExpanded = true;
33
31
  this.handleAsideExpand = (event) => {
34
32
  this.isAsideExpanded = event.detail.expanded;
@@ -96,6 +94,10 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
96
94
  }
97
95
  connectedCallback() {
98
96
  super.connectedCallback();
97
+ if (this.hasAttribute('ssr-has-sidebar')) {
98
+ this.hasSidebarSlot = true;
99
+ this.removeAttribute('ssr-has-sidebar');
100
+ }
99
101
  document.addEventListener('keydown', this.handleKeydown);
100
102
  }
101
103
  disconnectedCallback() {
@@ -116,6 +118,68 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
116
118
  }
117
119
  this.previousIsSmallViewport = this.isSmallViewport;
118
120
  }
121
+ static finalizeStyles(styles) {
122
+ const base = super.finalizeStyles(styles) ?? [];
123
+ return [
124
+ ...base,
125
+ unsafeCSS(`@layer quantic-header-visibility {
126
+ .header { display: none; }
127
+ .header.collapsible { display: revert-layer; }
128
+ }`),
129
+ whenSlotPresent('navbar', css `
130
+ @layer quantic-header-visibility {
131
+ .header {
132
+ display: revert-layer;
133
+ }
134
+ }
135
+ `),
136
+ whenSlotPresent('titlebar', css `
137
+ @layer quantic-header-visibility {
138
+ .header {
139
+ display: revert-layer;
140
+ }
141
+ }
142
+ `),
143
+ unsafeCSS(`@layer quantic-header-visibility {
144
+ :host(:has([slot="logo"]):not(:has([slot="sidebar"]))) .header { display: revert-layer; }
145
+ @scope { :scope:has([slot="logo"]):not(:has([slot="sidebar"])) .header { display: revert-layer; } }
146
+ }`),
147
+ whenSlotPresent('sidebar', css `
148
+ .aside { display: flex; }
149
+ @media only screen and (min-width: 1024px) {
150
+ .wrapper {
151
+ display: grid;
152
+ grid-template-areas: 'aside header' 'aside toolbar' 'aside main';
153
+ grid-template-rows: auto auto 1fr;
154
+ grid-template-columns: var(--quantic-component-layout-aside-width-collapsed) 1fr;
155
+ }
156
+ .is-aside-expanded.wrapper {
157
+ grid-template-columns: var(--quantic-component-layout-aside-width) 1fr;
158
+ }
159
+ .aside {
160
+ grid-area: aside;
161
+ position: sticky;
162
+ top: 0;
163
+ align-self: start;
164
+ transform: translateX(0);
165
+ opacity: 1;
166
+ pointer-events: auto;
167
+ }
168
+ .is-aside-expanded.wrapper .aside,
169
+ .is-aside-expanded.wrapper .logo {
170
+ width: var(--quantic-component-layout-aside-width);
171
+ }
172
+ .wrapper:not(.is-aside-expanded) .aside,
173
+ .wrapper:not(.is-aside-expanded) .logo {
174
+ width: var(--quantic-component-layout-aside-width-collapsed);
175
+ padding-inline: 0;
176
+ }
177
+ .toolbar { grid-area: toolbar; min-width: 0; }
178
+ .body { grid-area: main; min-width: 0; }
179
+ }
180
+ `),
181
+ ];
182
+ }
119
183
  get isAsideCollapsible() {
120
184
  return this.isSmallViewport && this.hasSidebar;
121
185
  }
@@ -125,12 +189,6 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
125
189
  get hasTitlebar() {
126
190
  return this.hasTitlebarSlot;
127
191
  }
128
- get hasHeader() {
129
- return (this.isAsideCollapsible ||
130
- this.hasTitlebarSlot ||
131
- this.hasNavbarSlot ||
132
- this.hasLogoSlot);
133
- }
134
192
  render() {
135
193
  const toggleButton = html `<quantic-button
136
194
  class="toggle-button"
@@ -146,7 +204,6 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
146
204
  const logo = html `<slot
147
205
  name="logo"
148
206
  class="logo"
149
- @slotchange=${onSlotChange((has) => (this.hasLogoSlot = has))}
150
207
  ></slot>`;
151
208
  const titlebar = html `<slot
152
209
  class="titlebar"
@@ -163,14 +220,13 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
163
220
  })}
164
221
  @expanded-changed=${this.handleAsideExpand}
165
222
  >
166
- <header class="header" ?hidden=${!this.hasHeader}>
223
+ <header class=${classMap({ header: true, collapsible: this.isAsideCollapsible })}>
167
224
  ${!this.hasSidebar ? logo : null}
168
225
  ${this.isAsideCollapsible ? toggleButton : null}
169
226
  ${this.isSmallViewport ? null : titlebar}
170
227
  <slot
171
228
  class="navbar"
172
229
  name="navbar"
173
- @slotchange=${onSlotChange((has) => (this.hasNavbarSlot = has))}
174
230
  ></slot>
175
231
  </header>
176
232
 
@@ -183,14 +239,12 @@ let Layout = class Layout extends AutoHideEmptySlotsMixin(QuanticElement, ['logo
183
239
 
184
240
  <div
185
241
  class="aside-backdrop"
186
- ?hidden=${!this.hasSidebar}
187
242
  aria-hidden="true"
188
243
  @click=${this.toggleAsideExpanded}
189
244
  ></div>
190
245
 
191
246
  <aside
192
247
  class="aside"
193
- ?hidden=${!this.hasSidebar}
194
248
  tabindex="-1"
195
249
  ?inert=${this.isSmallViewport && !this.isAsideExpanded}
196
250
  >
@@ -331,7 +385,7 @@ Layout.styles = css `
331
385
  padding-block: var(--quantic-component-layout-aside-padding-block);
332
386
  border-right: 1px solid var(--quantic-component-layout-aside-border);
333
387
  overflow: visible;
334
- display: flex;
388
+ display: none;
335
389
  flex-direction: column;
336
390
  gap: var(--quantic-component-layout-aside-padding-block);
337
391
  transform: translateX(
@@ -374,7 +428,7 @@ Layout.styles = css `
374
428
  opacity: 0;
375
429
  }
376
430
 
377
- .is-aside-expanded .aside-backdrop {
431
+ .has-sidebar.is-aside-expanded .aside-backdrop {
378
432
  display: block;
379
433
  pointer-events: auto;
380
434
  opacity: var(--quantic-component-layout-aside-backdrop-opacity);
@@ -399,8 +453,6 @@ Layout.styles = css `
399
453
 
400
454
  .header {
401
455
  grid-area: header;
402
- display: flex;
403
- align-items: center;
404
456
  }
405
457
 
406
458
  .logo {
@@ -427,7 +479,7 @@ Layout.styles = css `
427
479
  pointer-events: auto;
428
480
  }
429
481
 
430
- .is-aside-expanded .aside-backdrop {
482
+ .has-sidebar.is-aside-expanded .aside-backdrop {
431
483
  display: none;
432
484
  }
433
485
 
@@ -490,12 +542,6 @@ __decorate([
490
542
  __decorate([
491
543
  state()
492
544
  ], Layout.prototype, "hasTitlebarSlot", void 0);
493
- __decorate([
494
- state()
495
- ], Layout.prototype, "hasNavbarSlot", void 0);
496
- __decorate([
497
- state()
498
- ], Layout.prototype, "hasLogoSlot", void 0);
499
545
  __decorate([
500
546
  query('.aside')
501
547
  ], Layout.prototype, "asideElement", void 0);