@sken-ds/primitives 0.3.6 → 0.3.7
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/index.js +13 -11
- package/dist/sken-layout-region.js +30 -0
- package/dist/sken-layout-region.js.map +1 -0
- package/dist/sken-layout.js +205 -0
- package/dist/sken-layout.js.map +1 -0
- package/package.json +10 -2
package/dist/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { t as e } from "./sken-datatable-BtR-NwRN.js";
|
|
2
2
|
import { SkenButton as t } from "./sken-button.js";
|
|
3
3
|
import { SkenCheckbox as n } from "./sken-checkbox.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
4
|
+
import { SkenFilterChip as r } from "./sken-filter-chip.js";
|
|
5
|
+
import { SkenCombobox as i } from "./sken-combobox.js";
|
|
6
|
+
import { SkenComboboxGroup as a } from "./sken-combobox-group.js";
|
|
7
|
+
import { SkenComboboxItem as o } from "./sken-combobox-item.js";
|
|
8
|
+
import { SkenDatePicker as s } from "./sken-date-picker.js";
|
|
9
|
+
import { t as c } from "./sken-dialog-hRtML2jW.js";
|
|
10
|
+
import { SkenInput as l } from "./sken-input.js";
|
|
11
|
+
import { SkenLayoutRegion as u } from "./sken-layout-region.js";
|
|
12
|
+
import { SkenLayout as d } from "./sken-layout.js";
|
|
13
|
+
import { SkenNumberInput as f } from "./sken-number-input.js";
|
|
14
|
+
import { SkenSwitch as p } from "./sken-switch.js";
|
|
15
|
+
import { SkenTextarea as m } from "./sken-textarea.js";
|
|
16
|
+
export { t as SkenButton, n as SkenCheckbox, i as SkenCombobox, a as SkenComboboxGroup, o as SkenComboboxItem, e as SkenDataTable, s as SkenDatePicker, c as SkenDialog, r as SkenFilterChip, l as SkenInput, d as SkenLayout, u as SkenLayoutRegion, f as SkenNumberInput, p as SkenSwitch, m as SkenTextarea };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { t as e } from "./decorate-D4FKzyDw.js";
|
|
2
|
+
import { LitElement as t, css as n, html as r } from "lit";
|
|
3
|
+
import { customElement as i, property as a } from "lit/decorators.js";
|
|
4
|
+
//#region src/components/sken-layout-region.ts
|
|
5
|
+
var o = class extends t {
|
|
6
|
+
constructor(...e) {
|
|
7
|
+
super(...e), this.name = "content";
|
|
8
|
+
}
|
|
9
|
+
static {
|
|
10
|
+
this.styles = n`
|
|
11
|
+
/* 'display: contents' makes the region transparent in the
|
|
12
|
+
layout: it does not introduce a wrapper box, so the
|
|
13
|
+
consumer's children are sized and positioned as if they
|
|
14
|
+
were direct children of the host grid. The product can
|
|
15
|
+
override with 'display: block' (or anything else) if it
|
|
16
|
+
wants the region to be a real box. */
|
|
17
|
+
:host {
|
|
18
|
+
display: contents;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
}
|
|
22
|
+
render() {
|
|
23
|
+
return r`<slot></slot>`;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
e([a({ reflect: !0 })], o.prototype, "name", void 0), o = e([i("sken-layout-region")], o);
|
|
27
|
+
//#endregion
|
|
28
|
+
export { o as SkenLayoutRegion };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=sken-layout-region.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sken-layout-region.js","names":[],"sources":["../src/components/sken-layout-region.ts"],"sourcesContent":["// ── <sken-layout-region> — single cell of a <sken-layout> ──────────\n// The host element <sken-layout> places its light-DOM\n// <sken-layout-region> children into the page-level grid via the\n// `name` attribute (and CSS grid-area rules keyed off that name).\n// A region does not impose what lives inside it; it just gives\n// the grid a target to project into and lets the consumer style\n// the contents.\n//\n// Why this exists as a custom element (not a plain <div>):\n// - It lets the host's CSS select the slotted regions by tag +\n// attribute name across the shadow boundary (`::slotted(\n// sken-layout-region[name='topbar'])`), which is more robust\n// than relying on class names that the consumer might forget.\n// - It gives framework adapters a stable tag name to render\n// (Vue's <SkenLayoutRegion> resolves to <sken-layout-region>)\n// so the layout's CSS does not break if the consumer\n// re-organises their template.\n//\n// What the region does NOT do:\n// - It does not impose a default background, padding, or\n// typography. The product (or a future Sken layout pattern)\n// provides those via slot styling.\n// - It does not provide landmark roles. The consumer is\n// responsible for wrapping the contents in <header>, <nav>,\n// <main>, or <footer> as appropriate. A region called\n// `topbar` is *not* implicitly <header role=\"banner\">; the\n// product decides whether the topbar deserves the banner\n// landmark or whether that is reserved for a different layer.\n//\n// See ADR-0006 for the substrate decision. See\n// @sken-ds/contracts `SkenLayoutRegionProps` for the contract\n// surface.\n\nimport { LitElement, html, css } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport type { SkenLayoutRegionRole } from '@sken-ds/contracts'\n\n@customElement('sken-layout-region')\nexport class SkenLayoutRegion extends LitElement {\n @property({ reflect: true }) name: SkenLayoutRegionRole = 'content'\n\n static styles = css`\n /* 'display: contents' makes the region transparent in the\n layout: it does not introduce a wrapper box, so the\n consumer's children are sized and positioned as if they\n were direct children of the host grid. The product can\n override with 'display: block' (or anything else) if it\n wants the region to be a real box. */\n :host {\n display: contents;\n }\n `\n\n override render() {\n return html`<slot></slot>`\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sken-layout-region': SkenLayoutRegion\n }\n}\n"],"mappings":";;;;AAsCO,IAAM,IAAN,cAA+B,EAAW;;EACW,aAAA,KAAA,OAAA;;;EAE1C,KAAA,SAAA,CAAG;;;;;;;;;;;;CAYnB,SAAkB;EAChB,OAAO,CAAI;CACb;AACF;AAjBG,EAAA,CAAA,EAAS,EAAE,SAAS,GAAK,CAAC,CAAA,GAAA,EAAA,WAAA,QAAA,KAAA,CAAA,GAF5B,IAAA,EAAA,CAAA,EAAc,oBAAoB,CAAA,GAAA,CAAA"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { t as e } from "./decorate-D4FKzyDw.js";
|
|
2
|
+
import "./sken-layout-region.js";
|
|
3
|
+
import { LitElement as t, css as n, html as r, unsafeCSS as i } from "lit";
|
|
4
|
+
import { customElement as a, property as o } from "lit/decorators.js";
|
|
5
|
+
//#region src/components/sken-layout.ts
|
|
6
|
+
var s = {
|
|
7
|
+
sm: "12rem",
|
|
8
|
+
md: "16rem",
|
|
9
|
+
lg: "20rem"
|
|
10
|
+
}, c = class extends t {
|
|
11
|
+
constructor(...e) {
|
|
12
|
+
super(...e), this.variant = "header-content", this.topbarMode = "fixed", this.sidebarPosition = "start", this.sidebarSize = "md";
|
|
13
|
+
}
|
|
14
|
+
static {
|
|
15
|
+
this.styles = n`
|
|
16
|
+
/* ── The host ────────────────────────────────────────────────
|
|
17
|
+
The host owns the page-level grid. The body row is a
|
|
18
|
+
sub-grid; the topbar / primary-nav / footer sit in their
|
|
19
|
+
own rows. The shadow DOM owns the layout; the slot inside
|
|
20
|
+
projects the consumer's regions into the grid cells. */
|
|
21
|
+
:host {
|
|
22
|
+
display: grid;
|
|
23
|
+
block-size: 100dvh;
|
|
24
|
+
grid-template-columns: 1fr;
|
|
25
|
+
grid-template-rows: auto 1fr;
|
|
26
|
+
grid-template-areas:
|
|
27
|
+
'topbar'
|
|
28
|
+
'body';
|
|
29
|
+
background: var(--sken-background, Canvas);
|
|
30
|
+
color: var(--sken-foreground, CanvasText);
|
|
31
|
+
font-family: var(--sken-family-sans, system-ui, sans-serif);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.body {
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: 1fr;
|
|
37
|
+
grid-template-areas: 'content';
|
|
38
|
+
min-block-size: 0; /* allow children to shrink + scroll */
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.body.with-sidebar {
|
|
42
|
+
grid-template-columns: var(--sken-layout-sidebar-width, 16rem) 1fr;
|
|
43
|
+
grid-template-areas: 'sidebar content';
|
|
44
|
+
}
|
|
45
|
+
.body.with-sidebar.sidebar-end {
|
|
46
|
+
grid-template-columns: 1fr var(--sken-layout-sidebar-width, 16rem);
|
|
47
|
+
grid-template-areas: 'content sidebar';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ── Per-region grid placement ───────────────────────────────
|
|
51
|
+
The light-DOM <sken-layout-region> children are projected
|
|
52
|
+
here through the unnamed <slot>. The grid-area rule per
|
|
53
|
+
name positions each one in the right cell. We select the
|
|
54
|
+
slotted custom elements by attribute, which works
|
|
55
|
+
transparently across the shadow boundary. */
|
|
56
|
+
::slotted(sken-layout-region[name='topbar']) {
|
|
57
|
+
grid-area: topbar;
|
|
58
|
+
}
|
|
59
|
+
::slotted(sken-layout-region[name='primary-nav']) {
|
|
60
|
+
grid-area: primary-nav;
|
|
61
|
+
}
|
|
62
|
+
::slotted(sken-layout-region[name='sidebar']) {
|
|
63
|
+
grid-area: sidebar;
|
|
64
|
+
min-block-size: 0;
|
|
65
|
+
border-inline-end: 1px solid
|
|
66
|
+
var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));
|
|
67
|
+
}
|
|
68
|
+
::slotted(sken-layout-region[name='content']) {
|
|
69
|
+
grid-area: content;
|
|
70
|
+
min-block-size: 0;
|
|
71
|
+
}
|
|
72
|
+
::slotted(sken-layout-region[name='footer']) {
|
|
73
|
+
grid-area: footer;
|
|
74
|
+
border-top: 1px solid
|
|
75
|
+
var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* ── Grid templates per variant ─────────────────────────────── */
|
|
79
|
+
:host([variant='full-bleed']) {
|
|
80
|
+
grid-template-areas: 'body';
|
|
81
|
+
grid-template-rows: 1fr;
|
|
82
|
+
}
|
|
83
|
+
:host([variant='header-content']) {
|
|
84
|
+
grid-template-areas:
|
|
85
|
+
'topbar'
|
|
86
|
+
'body';
|
|
87
|
+
grid-template-rows: auto 1fr;
|
|
88
|
+
}
|
|
89
|
+
:host([variant='sidebar-content']) {
|
|
90
|
+
grid-template-rows: 1fr;
|
|
91
|
+
grid-template-areas: 'body';
|
|
92
|
+
}
|
|
93
|
+
:host([variant='sidebar-content']) .body {
|
|
94
|
+
grid-template-columns: var(--sken-layout-sidebar-width, 16rem) 1fr;
|
|
95
|
+
grid-template-areas: 'sidebar content';
|
|
96
|
+
}
|
|
97
|
+
:host([variant='header-sidebar']) {
|
|
98
|
+
grid-template-rows: auto auto 1fr;
|
|
99
|
+
grid-template-areas:
|
|
100
|
+
'topbar'
|
|
101
|
+
'primary-nav'
|
|
102
|
+
'body';
|
|
103
|
+
}
|
|
104
|
+
:host([variant='header-sidebar-footer']) {
|
|
105
|
+
grid-template-rows: auto auto 1fr auto;
|
|
106
|
+
grid-template-areas:
|
|
107
|
+
'topbar'
|
|
108
|
+
'primary-nav'
|
|
109
|
+
'body'
|
|
110
|
+
'footer';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ── Topbar mode ──────────────────────────────────────────────
|
|
114
|
+
'fixed': the host is 100dvh and the body scrolls under the
|
|
115
|
+
topbar. This is the default for admin consoles.
|
|
116
|
+
'auto': the topbar scrolls away with the page (marketing,
|
|
117
|
+
landing). */
|
|
118
|
+
:host([topbar-mode='auto']) {
|
|
119
|
+
block-size: auto;
|
|
120
|
+
min-block-size: 100dvh;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ── Sidebar position ─────────────────────────────────────────
|
|
124
|
+
The 'with-sidebar' class is applied via JS in render() so
|
|
125
|
+
we can include the 'sidebar-end' modifier in the same
|
|
126
|
+
selector chain. (You cannot combine the [sidebar-position]
|
|
127
|
+
attribute with the '.with-sidebar' class in a single
|
|
128
|
+
selector, because the class is conditional.) */
|
|
129
|
+
:host([sidebar-position='end']) ::slotted(sken-layout-region[name='sidebar']) {
|
|
130
|
+
border-inline-end: none;
|
|
131
|
+
border-inline-start: 1px solid
|
|
132
|
+
var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* ── Sidebar width override ─────────────────────────────────── */
|
|
136
|
+
:host([sidebar-size='sm']) {
|
|
137
|
+
--sken-layout-sidebar-width: ${i(s.sm)};
|
|
138
|
+
}
|
|
139
|
+
:host([sidebar-size='md']) {
|
|
140
|
+
--sken-layout-sidebar-width: ${i(s.md)};
|
|
141
|
+
}
|
|
142
|
+
:host([sidebar-size='lg']) {
|
|
143
|
+
--sken-layout-sidebar-width: ${i(s.lg)};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* ── Variant-aware region hiding ─────────────────────────────
|
|
147
|
+
Roles the active variant does not include are hidden
|
|
148
|
+
outright. This way a consumer that always renders the
|
|
149
|
+
same set of regions (e.g. a shared layout component) does
|
|
150
|
+
not get phantom space when a page uses a different
|
|
151
|
+
variant. */
|
|
152
|
+
:host([variant='full-bleed']) ::slotted(sken-layout-region[name='topbar']),
|
|
153
|
+
:host([variant='full-bleed']) ::slotted(sken-layout-region[name='primary-nav']),
|
|
154
|
+
:host([variant='full-bleed']) ::slotted(sken-layout-region[name='sidebar']),
|
|
155
|
+
:host([variant='full-bleed']) ::slotted(sken-layout-region[name='footer']) {
|
|
156
|
+
display: none;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
:host([variant='header-content']) ::slotted(sken-layout-region[name='primary-nav']),
|
|
160
|
+
:host([variant='header-content']) ::slotted(sken-layout-region[name='sidebar']),
|
|
161
|
+
:host([variant='header-content']) ::slotted(sken-layout-region[name='footer']) {
|
|
162
|
+
display: none;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
:host([variant='sidebar-content']) ::slotted(sken-layout-region[name='topbar']),
|
|
166
|
+
:host([variant='sidebar-content']) ::slotted(sken-layout-region[name='primary-nav']),
|
|
167
|
+
:host([variant='sidebar-content']) ::slotted(sken-layout-region[name='footer']) {
|
|
168
|
+
display: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
:host([variant='header-sidebar']) ::slotted(sken-layout-region[name='footer']) {
|
|
172
|
+
display: none;
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
175
|
+
}
|
|
176
|
+
render() {
|
|
177
|
+
let e = this.#e(this.variant), t = [
|
|
178
|
+
"body",
|
|
179
|
+
e ? "with-sidebar" : "",
|
|
180
|
+
e && this.sidebarPosition === "end" ? "sidebar-end" : ""
|
|
181
|
+
].filter(Boolean).join(" ");
|
|
182
|
+
return r`
|
|
183
|
+
<div class=${t} part="body">
|
|
184
|
+
<slot></slot>
|
|
185
|
+
</div>
|
|
186
|
+
`;
|
|
187
|
+
}
|
|
188
|
+
#e(e) {
|
|
189
|
+
return e === "sidebar-content" || e === "header-sidebar" || e === "header-sidebar-footer";
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
e([o({ reflect: !0 })], c.prototype, "variant", void 0), e([o({
|
|
193
|
+
attribute: "topbar-mode",
|
|
194
|
+
reflect: !0
|
|
195
|
+
})], c.prototype, "topbarMode", void 0), e([o({
|
|
196
|
+
attribute: "sidebar-position",
|
|
197
|
+
reflect: !0
|
|
198
|
+
})], c.prototype, "sidebarPosition", void 0), e([o({
|
|
199
|
+
attribute: "sidebar-size",
|
|
200
|
+
reflect: !0
|
|
201
|
+
})], c.prototype, "sidebarSize", void 0), c = e([a("sken-layout")], c);
|
|
202
|
+
//#endregion
|
|
203
|
+
export { c as SkenLayout };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=sken-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sken-layout.js","names":["#variantHasSidebar"],"sources":["../src/components/sken-layout.ts"],"sourcesContent":["// ── <sken-layout> — structural layout primitive ────────────────────\n// Defines the page-level structure of a multi-region interface\n// (topbar, primary nav, sidebar, content, footer) without imposing\n// what lives inside each region. Composition by contract:\n//\n// <sken-layout variant=\"header-sidebar\">\n// <sken-layout-region name=\"topbar\">…</sken-layout-region>\n// <sken-layout-region name=\"primary-nav\">…</sken-layout-region>\n// <sken-layout-region name=\"sidebar\">…</sken-layout-region>\n// <sken-layout-region name=\"content\">…</sken-layout-region>\n// </sken-layout>\n//\n// Design notes:\n// - We project the light-DOM regions into a shadow-DOM grid via\n// a single <slot>. Inside the shadow we own the grid template\n// + per-name `grid-area` CSS rules; the consumer's regions\n// sit in the slot. Empty regions (no consumer region for a\n// name) simply do not project; the grid still has the area\n// declared but the slot stays empty, so no space is reserved.\n// - We DO NOT use named <slot name=\"topbar\"> etc. because that\n// would force the consumer to keep the regions in a fixed\n// order. A single unnamed <slot> lets the consumer arrange\n// the regions in any order; the grid-area CSS rule per name\n// is what places them in the layout. (A Vue adapter that\n// renders regions via <template v-for> is therefore free.)\n// - For roles the active variant does not include, we hide\n// the region via `display: none` so a consumer that always\n// renders the same set of regions (e.g. from a layout\n// component shared across pages) does not get phantom space.\n// The CSS rule uses `:host([variant=…])` so it does not\n// depend on JS state.\n//\n// See ADR-0006 for the substrate decision. See the\n// @sken-ds/contracts types `SkenLayoutProps`, `SkenLayoutSlots`,\n// `SkenLayoutVariant` for the contract surface.\n\nimport { LitElement, html, css, unsafeCSS } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport type {\n SkenLayoutVariant,\n SkenLayoutTopbarMode,\n SkenLayoutSidebarPosition,\n SkenLayoutSidebarSize,\n} from '@sken-ds/contracts'\nimport './sken-layout-region.js'\n\n/**\n * Sidebar width in `rem` per size concept. The product can\n * override with `--sken-layout-sidebar-width` (CSS custom\n * property) if it needs a different value.\n */\nconst SIDEBAR_WIDTH: Record<SkenLayoutSidebarSize, string> = {\n sm: '12rem',\n md: '16rem',\n lg: '20rem',\n}\n\n@customElement('sken-layout')\nexport class SkenLayout extends LitElement {\n @property({ reflect: true }) variant: SkenLayoutVariant = 'header-content'\n @property({ attribute: 'topbar-mode', reflect: true }) topbarMode: SkenLayoutTopbarMode = 'fixed'\n @property({ attribute: 'sidebar-position', reflect: true })\n sidebarPosition: SkenLayoutSidebarPosition = 'start'\n @property({ attribute: 'sidebar-size', reflect: true }) sidebarSize: SkenLayoutSidebarSize = 'md'\n\n static styles = css`\n /* ── The host ────────────────────────────────────────────────\n The host owns the page-level grid. The body row is a\n sub-grid; the topbar / primary-nav / footer sit in their\n own rows. The shadow DOM owns the layout; the slot inside\n projects the consumer's regions into the grid cells. */\n :host {\n display: grid;\n block-size: 100dvh;\n grid-template-columns: 1fr;\n grid-template-rows: auto 1fr;\n grid-template-areas:\n 'topbar'\n 'body';\n background: var(--sken-background, Canvas);\n color: var(--sken-foreground, CanvasText);\n font-family: var(--sken-family-sans, system-ui, sans-serif);\n }\n\n .body {\n display: grid;\n grid-template-columns: 1fr;\n grid-template-areas: 'content';\n min-block-size: 0; /* allow children to shrink + scroll */\n }\n\n .body.with-sidebar {\n grid-template-columns: var(--sken-layout-sidebar-width, 16rem) 1fr;\n grid-template-areas: 'sidebar content';\n }\n .body.with-sidebar.sidebar-end {\n grid-template-columns: 1fr var(--sken-layout-sidebar-width, 16rem);\n grid-template-areas: 'content sidebar';\n }\n\n /* ── Per-region grid placement ───────────────────────────────\n The light-DOM <sken-layout-region> children are projected\n here through the unnamed <slot>. The grid-area rule per\n name positions each one in the right cell. We select the\n slotted custom elements by attribute, which works\n transparently across the shadow boundary. */\n ::slotted(sken-layout-region[name='topbar']) {\n grid-area: topbar;\n }\n ::slotted(sken-layout-region[name='primary-nav']) {\n grid-area: primary-nav;\n }\n ::slotted(sken-layout-region[name='sidebar']) {\n grid-area: sidebar;\n min-block-size: 0;\n border-inline-end: 1px solid\n var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));\n }\n ::slotted(sken-layout-region[name='content']) {\n grid-area: content;\n min-block-size: 0;\n }\n ::slotted(sken-layout-region[name='footer']) {\n grid-area: footer;\n border-top: 1px solid\n var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));\n }\n\n /* ── Grid templates per variant ─────────────────────────────── */\n :host([variant='full-bleed']) {\n grid-template-areas: 'body';\n grid-template-rows: 1fr;\n }\n :host([variant='header-content']) {\n grid-template-areas:\n 'topbar'\n 'body';\n grid-template-rows: auto 1fr;\n }\n :host([variant='sidebar-content']) {\n grid-template-rows: 1fr;\n grid-template-areas: 'body';\n }\n :host([variant='sidebar-content']) .body {\n grid-template-columns: var(--sken-layout-sidebar-width, 16rem) 1fr;\n grid-template-areas: 'sidebar content';\n }\n :host([variant='header-sidebar']) {\n grid-template-rows: auto auto 1fr;\n grid-template-areas:\n 'topbar'\n 'primary-nav'\n 'body';\n }\n :host([variant='header-sidebar-footer']) {\n grid-template-rows: auto auto 1fr auto;\n grid-template-areas:\n 'topbar'\n 'primary-nav'\n 'body'\n 'footer';\n }\n\n /* ── Topbar mode ──────────────────────────────────────────────\n 'fixed': the host is 100dvh and the body scrolls under the\n topbar. This is the default for admin consoles.\n 'auto': the topbar scrolls away with the page (marketing,\n landing). */\n :host([topbar-mode='auto']) {\n block-size: auto;\n min-block-size: 100dvh;\n }\n\n /* ── Sidebar position ─────────────────────────────────────────\n The 'with-sidebar' class is applied via JS in render() so\n we can include the 'sidebar-end' modifier in the same\n selector chain. (You cannot combine the [sidebar-position]\n attribute with the '.with-sidebar' class in a single\n selector, because the class is conditional.) */\n :host([sidebar-position='end']) ::slotted(sken-layout-region[name='sidebar']) {\n border-inline-end: none;\n border-inline-start: 1px solid\n var(--sken-border, color-mix(in srgb, currentColor 12%, transparent));\n }\n\n /* ── Sidebar width override ─────────────────────────────────── */\n :host([sidebar-size='sm']) {\n --sken-layout-sidebar-width: ${unsafeCSS(SIDEBAR_WIDTH.sm)};\n }\n :host([sidebar-size='md']) {\n --sken-layout-sidebar-width: ${unsafeCSS(SIDEBAR_WIDTH.md)};\n }\n :host([sidebar-size='lg']) {\n --sken-layout-sidebar-width: ${unsafeCSS(SIDEBAR_WIDTH.lg)};\n }\n\n /* ── Variant-aware region hiding ─────────────────────────────\n Roles the active variant does not include are hidden\n outright. This way a consumer that always renders the\n same set of regions (e.g. a shared layout component) does\n not get phantom space when a page uses a different\n variant. */\n :host([variant='full-bleed']) ::slotted(sken-layout-region[name='topbar']),\n :host([variant='full-bleed']) ::slotted(sken-layout-region[name='primary-nav']),\n :host([variant='full-bleed']) ::slotted(sken-layout-region[name='sidebar']),\n :host([variant='full-bleed']) ::slotted(sken-layout-region[name='footer']) {\n display: none;\n }\n\n :host([variant='header-content']) ::slotted(sken-layout-region[name='primary-nav']),\n :host([variant='header-content']) ::slotted(sken-layout-region[name='sidebar']),\n :host([variant='header-content']) ::slotted(sken-layout-region[name='footer']) {\n display: none;\n }\n\n :host([variant='sidebar-content']) ::slotted(sken-layout-region[name='topbar']),\n :host([variant='sidebar-content']) ::slotted(sken-layout-region[name='primary-nav']),\n :host([variant='sidebar-content']) ::slotted(sken-layout-region[name='footer']) {\n display: none;\n }\n\n :host([variant='header-sidebar']) ::slotted(sken-layout-region[name='footer']) {\n display: none;\n }\n `\n\n override render() {\n const hasSidebar = this.#variantHasSidebar(this.variant)\n const bodyClasses = [\n 'body',\n hasSidebar ? 'with-sidebar' : '',\n hasSidebar && this.sidebarPosition === 'end' ? 'sidebar-end' : '',\n ]\n .filter(Boolean)\n .join(' ')\n\n return html`\n <div class=${bodyClasses} part=\"body\">\n <slot></slot>\n </div>\n `\n }\n\n /**\n * Single source of truth for which variants include a sidebar.\n * Used to apply the `.with-sidebar` class on the body grid\n * wrapper. Mirrors the per-variant CSS templates above.\n */\n #variantHasSidebar(variant: SkenLayoutVariant): boolean {\n return variant === 'sidebar-content' || variant === 'header-sidebar' || variant === 'header-sidebar-footer'\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'sken-layout': SkenLayout\n }\n}\n"],"mappings":";;;;;AAmDA,IAAM,IAAuD;CAC3D,IAAI;CACJ,IAAI;CACJ,IAAI;AACN,GAGa,IAAN,cAAyB,EAAW;;EAKoD,aAJnC,KAAA,UAAA,kBACgC,KAAA,aAAA,SAE7C,KAAA,kBAAA,SACgD,KAAA,cAAA;;;EAE7E,KAAA,SAAA,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCA0HgB,EAAU,EAAc,EAAE,EAAE;;;qCAG5B,EAAU,EAAc,EAAE,EAAE;;;qCAG5B,EAAU,EAAc,EAAE,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiC/D,SAAkB;EAChB,IAAM,IAAa,KAAKA,GAAmB,KAAK,OAAO,GACjD,IAAc;GAClB;GACA,IAAa,iBAAiB;GAC9B,KAAc,KAAK,oBAAoB,QAAQ,gBAAgB;EACjE,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EAEX,OAAO,CAAI;mBACI,EAAY;;;;CAI7B;CAOA,GAAmB,GAAqC;EACtD,OAAO,MAAY,qBAAqB,MAAY,oBAAoB,MAAY;CACtF;AACF;AAhMG,EAAA,CAAA,EAAS,EAAE,SAAS,GAAK,CAAC,CAAA,GAAA,EAAA,WAAA,WAAA,KAAA,CAAA,GAC1B,EAAA,CAAA,EAAS;CAAE,WAAW;CAAe,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,cAAA,KAAA,CAAA,GACpD,EAAA,CAAA,EAAS;CAAE,WAAW;CAAoB,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,mBAAA,KAAA,CAAA,GAEzD,EAAA,CAAA,EAAS;CAAE,WAAW;CAAgB,SAAS;AAAK,CAAC,CAAA,GAAA,EAAA,WAAA,eAAA,KAAA,CAAA,GANvD,IAAA,EAAA,CAAA,EAAc,aAAa,CAAA,GAAA,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sken-ds/primitives",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org",
|
|
6
6
|
"access": "public"
|
|
@@ -31,6 +31,14 @@
|
|
|
31
31
|
"types": "./dist/sken-input.d.ts",
|
|
32
32
|
"import": "./dist/sken-input.js"
|
|
33
33
|
},
|
|
34
|
+
"./sken-layout": {
|
|
35
|
+
"types": "./dist/sken-layout.d.ts",
|
|
36
|
+
"import": "./dist/sken-layout.js"
|
|
37
|
+
},
|
|
38
|
+
"./sken-layout-region": {
|
|
39
|
+
"types": "./dist/sken-layout-region.d.ts",
|
|
40
|
+
"import": "./dist/sken-layout-region.js"
|
|
41
|
+
},
|
|
34
42
|
"./sken-number-input": {
|
|
35
43
|
"types": "./dist/sken-number-input.d.ts",
|
|
36
44
|
"import": "./dist/sken-number-input.js"
|
|
@@ -84,7 +92,7 @@
|
|
|
84
92
|
"@tanstack/match-sorter-utils": "^9.0.0",
|
|
85
93
|
"@tanstack/table-core": "^9.0.0",
|
|
86
94
|
"lit": "^3.3.3",
|
|
87
|
-
"@sken-ds/contracts": "0.3.
|
|
95
|
+
"@sken-ds/contracts": "0.3.7"
|
|
88
96
|
},
|
|
89
97
|
"devDependencies": {
|
|
90
98
|
"@vitest/coverage-v8": "^4.1.10",
|