@deepfuture/dui-components 0.0.16 → 0.0.17
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/README.md +32 -0
- package/accordion/accordion-item.js +0 -19
- package/card-grid/card-grid.d.ts +17 -0
- package/card-grid/card-grid.js +110 -0
- package/card-grid/index.d.ts +3 -0
- package/card-grid/index.js +3 -0
- package/collapsible/collapsible.js +3 -17
- package/command/command-empty.js +1 -1
- package/command/command-group.js +1 -1
- package/command/command-item.js +1 -1
- package/package.json +6 -2
- package/popover/popover-popup.js +5 -1
- package/preview-card/preview-card-popup.js +5 -1
- package/tabs/tabs-panel.d.ts +2 -2
- package/tabs/tabs-panel.js +9 -15
- package/tooltip/tooltip-popup.js +5 -1
package/README.md
CHANGED
|
@@ -146,6 +146,36 @@ DUI uses CSS custom properties for theming. Toggle dark mode by adding `class="d
|
|
|
146
146
|
</body>
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
## Templates
|
|
150
|
+
|
|
151
|
+
Pre-composed UI patterns built from DUI components — ready-to-use cards, feed items, and other building blocks. Templates are theme-scoped: they use the default theme's variant vocabulary and tokens, so they adapt automatically to dark mode and custom token overrides.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npm install @deepfuture/dui-theme-default-templates
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { DuiFeedItem } from "@deepfuture/dui-theme-default-templates/feed";
|
|
159
|
+
|
|
160
|
+
applyTheme({
|
|
161
|
+
theme: defaultTheme,
|
|
162
|
+
components: [DuiFeedItem], // dependencies (DuiBadge, etc.) auto-register
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```html
|
|
167
|
+
<dui-feed-item
|
|
168
|
+
title="Earthquake detected"
|
|
169
|
+
subtitle="USGS Pacific Northwest"
|
|
170
|
+
timestamp="2 min ago"
|
|
171
|
+
category="Seismic"
|
|
172
|
+
severity="high"
|
|
173
|
+
description="Magnitude 4.2 recorded near Portland, OR."
|
|
174
|
+
></dui-feed-item>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Templates declare their component dependencies via `static dependencies` — `applyTheme` auto-registers them, so you don't need to import `DuiBadge` separately.
|
|
178
|
+
|
|
149
179
|
## Packages
|
|
150
180
|
|
|
151
181
|
| Package | Purpose |
|
|
@@ -153,6 +183,7 @@ DUI uses CSS custom properties for theming. Toggle dark mode by adding `class="d
|
|
|
153
183
|
| [`@deepfuture/dui-core`](https://www.npmjs.com/package/@deepfuture/dui-core) | `applyTheme()`, event factory, base styles |
|
|
154
184
|
| [`@deepfuture/dui-components`](https://www.npmjs.com/package/@deepfuture/dui-components) | Unstyled component classes |
|
|
155
185
|
| [`@deepfuture/dui-theme-default`](https://www.npmjs.com/package/@deepfuture/dui-theme-default) | Design tokens + aesthetic styles |
|
|
186
|
+
| [`@deepfuture/dui-theme-default-templates`](https://www.npmjs.com/package/@deepfuture/dui-theme-default-templates) | Pre-composed UI patterns for the default theme |
|
|
156
187
|
| [`@deepfuture/dui-cdn`](https://www.npmjs.com/package/@deepfuture/dui-cdn) | Pre-bundled CDN build (all deps inlined) |
|
|
157
188
|
|
|
158
189
|
## Dev Tools
|
|
@@ -177,6 +208,7 @@ See **[Inspector docs](docs/inspector.md)** for the full API reference and usage
|
|
|
177
208
|
- **[Live Docs](https://deepfuturenow.github.io/dui/)** — interactive demos for every component
|
|
178
209
|
- [Architecture](docs/architecture.md) — mental model, package responsibilities, design decisions
|
|
179
210
|
- [Creating Components](docs/creating-components.md) — guide for adding new components
|
|
211
|
+
- [Creating Templates](docs/creating-templates.md) — guide for building theme-scoped templates
|
|
180
212
|
- [Theming](docs/theming.md) — theme system, design tokens, writing component styles
|
|
181
213
|
- [Consuming](docs/consuming.md) — integrating DUI into an app
|
|
182
214
|
- [Inspector](docs/inspector.md) — runtime inspection, mutation API, and visual editor
|
|
@@ -67,30 +67,12 @@ const styles = css `
|
|
|
67
67
|
cursor: default;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
[part="indicator"] {
|
|
71
|
-
flex-shrink: 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
70
|
[part="panel"] {
|
|
75
71
|
overflow: hidden;
|
|
76
72
|
contain: content;
|
|
77
73
|
transition-property: height;
|
|
78
74
|
}
|
|
79
75
|
`;
|
|
80
|
-
// Inline chevron-down SVG to avoid icon component dependency
|
|
81
|
-
const chevronSvg = html `<svg
|
|
82
|
-
part="indicator"
|
|
83
|
-
width="16"
|
|
84
|
-
height="16"
|
|
85
|
-
viewBox="0 0 24 24"
|
|
86
|
-
fill="none"
|
|
87
|
-
stroke="currentColor"
|
|
88
|
-
stroke-width="2"
|
|
89
|
-
stroke-linecap="round"
|
|
90
|
-
stroke-linejoin="round"
|
|
91
|
-
>
|
|
92
|
-
<path d="m6 9 6 6 6-6" />
|
|
93
|
-
</svg>`;
|
|
94
76
|
let DuiAccordionItem = (() => {
|
|
95
77
|
let _classSuper = LitElement;
|
|
96
78
|
let _value_decorators;
|
|
@@ -292,7 +274,6 @@ let DuiAccordionItem = (() => {
|
|
|
292
274
|
@keydown=${this.#onKeyDown}
|
|
293
275
|
>
|
|
294
276
|
<slot name="trigger"></slot>
|
|
295
|
-
${chevronSvg}
|
|
296
277
|
</button>
|
|
297
278
|
</h3>
|
|
298
279
|
${shouldRender
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LitElement, type TemplateResult } from "lit";
|
|
2
|
+
/**
|
|
3
|
+
* `<dui-card-grid>` — A responsive grid layout for cards and panels.
|
|
4
|
+
*
|
|
5
|
+
* Distributes children into equal-width columns that collapse at narrow
|
|
6
|
+
* container widths. Use `columns` to set the maximum column count.
|
|
7
|
+
*
|
|
8
|
+
* @slot - Grid children (cards, panels, or any block content).
|
|
9
|
+
* @csspart root - The grid container element.
|
|
10
|
+
*/
|
|
11
|
+
export declare class DuiCardGrid extends LitElement {
|
|
12
|
+
static tagName: "dui-card-grid";
|
|
13
|
+
static styles: import("lit").CSSResult[];
|
|
14
|
+
/** Maximum number of columns (1–4). Responsive breakpoints reduce this automatically. */
|
|
15
|
+
accessor columns: string;
|
|
16
|
+
render(): TemplateResult;
|
|
17
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import { css, html, LitElement } from "lit";
|
|
36
|
+
import { property } from "lit/decorators.js";
|
|
37
|
+
import { base } from "@deepfuture/dui-core/base";
|
|
38
|
+
/** Structural styles only — layout CSS. */
|
|
39
|
+
const styles = css `
|
|
40
|
+
:host {
|
|
41
|
+
display: block;
|
|
42
|
+
min-width: 100%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[part="root"] {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: repeat(var(--_columns, 3), 1fr);
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
:host([columns="1"]) { --_columns: 1; }
|
|
52
|
+
:host([columns="2"]) { --_columns: 2; }
|
|
53
|
+
:host([columns="3"]) { --_columns: 3; }
|
|
54
|
+
:host([columns="4"]) { --_columns: 4; }
|
|
55
|
+
|
|
56
|
+
/* Responsive collapse: narrow viewports reduce columns */
|
|
57
|
+
@media (max-width: 768px) {
|
|
58
|
+
:host([columns="3"]) { --_columns: 2; }
|
|
59
|
+
:host([columns="4"]) { --_columns: 2; }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@media (max-width: 480px) {
|
|
63
|
+
:host([columns="2"]),
|
|
64
|
+
:host([columns="3"]),
|
|
65
|
+
:host([columns="4"]) {
|
|
66
|
+
--_columns: 1;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
70
|
+
/**
|
|
71
|
+
* `<dui-card-grid>` — A responsive grid layout for cards and panels.
|
|
72
|
+
*
|
|
73
|
+
* Distributes children into equal-width columns that collapse at narrow
|
|
74
|
+
* container widths. Use `columns` to set the maximum column count.
|
|
75
|
+
*
|
|
76
|
+
* @slot - Grid children (cards, panels, or any block content).
|
|
77
|
+
* @csspart root - The grid container element.
|
|
78
|
+
*/
|
|
79
|
+
let DuiCardGrid = (() => {
|
|
80
|
+
let _classSuper = LitElement;
|
|
81
|
+
let _columns_decorators;
|
|
82
|
+
let _columns_initializers = [];
|
|
83
|
+
let _columns_extraInitializers = [];
|
|
84
|
+
return class DuiCardGrid extends _classSuper {
|
|
85
|
+
static {
|
|
86
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
87
|
+
_columns_decorators = [property({ reflect: true })];
|
|
88
|
+
__esDecorate(this, null, _columns_decorators, { kind: "accessor", name: "columns", static: false, private: false, access: { has: obj => "columns" in obj, get: obj => obj.columns, set: (obj, value) => { obj.columns = value; } }, metadata: _metadata }, _columns_initializers, _columns_extraInitializers);
|
|
89
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
90
|
+
}
|
|
91
|
+
static tagName = "dui-card-grid";
|
|
92
|
+
static styles = [base, styles];
|
|
93
|
+
#columns_accessor_storage = __runInitializers(this, _columns_initializers, "3");
|
|
94
|
+
/** Maximum number of columns (1–4). Responsive breakpoints reduce this automatically. */
|
|
95
|
+
get columns() { return this.#columns_accessor_storage; }
|
|
96
|
+
set columns(value) { this.#columns_accessor_storage = value; }
|
|
97
|
+
render() {
|
|
98
|
+
return html `
|
|
99
|
+
<div part="root">
|
|
100
|
+
<slot></slot>
|
|
101
|
+
</div>
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
constructor() {
|
|
105
|
+
super(...arguments);
|
|
106
|
+
__runInitializers(this, _columns_extraInitializers);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
})();
|
|
110
|
+
export { DuiCardGrid };
|
|
@@ -65,8 +65,9 @@ const styles = css `
|
|
|
65
65
|
cursor: default;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
[
|
|
69
|
-
flex
|
|
68
|
+
slot[name="trigger"] {
|
|
69
|
+
flex: 1;
|
|
70
|
+
min-width: 0;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
[part="panel"] {
|
|
@@ -75,20 +76,6 @@ const styles = css `
|
|
|
75
76
|
transition-property: height;
|
|
76
77
|
}
|
|
77
78
|
`;
|
|
78
|
-
// Inline chevron-down SVG to avoid icon component dependency
|
|
79
|
-
const chevronSvg = html `<svg
|
|
80
|
-
part="indicator"
|
|
81
|
-
width="16"
|
|
82
|
-
height="16"
|
|
83
|
-
viewBox="0 0 24 24"
|
|
84
|
-
fill="none"
|
|
85
|
-
stroke="currentColor"
|
|
86
|
-
stroke-width="2"
|
|
87
|
-
stroke-linecap="round"
|
|
88
|
-
stroke-linejoin="round"
|
|
89
|
-
>
|
|
90
|
-
<path d="m6 9 6 6 6-6" />
|
|
91
|
-
</svg>`;
|
|
92
79
|
let DuiCollapsible = (() => {
|
|
93
80
|
let _classSuper = LitElement;
|
|
94
81
|
let _open_decorators;
|
|
@@ -277,7 +264,6 @@ let DuiCollapsible = (() => {
|
|
|
277
264
|
@click=${this.#onClick}
|
|
278
265
|
>
|
|
279
266
|
<slot name="trigger"></slot>
|
|
280
|
-
${chevronSvg}
|
|
281
267
|
</button>
|
|
282
268
|
${shouldRender
|
|
283
269
|
? html `
|
package/command/command-empty.js
CHANGED
package/command/command-group.js
CHANGED
package/command/command-item.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepfuture/dui-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "DUI unstyled web components — structural CSS only, themed via applyTheme()",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -174,6 +174,10 @@
|
|
|
174
174
|
"import": "./split-button/index.js",
|
|
175
175
|
"types": "./split-button/index.d.ts"
|
|
176
176
|
},
|
|
177
|
+
"./card-grid": {
|
|
178
|
+
"import": "./card-grid/index.js",
|
|
179
|
+
"types": "./card-grid/index.d.ts"
|
|
180
|
+
},
|
|
177
181
|
"./all": {
|
|
178
182
|
"import": "./all.js",
|
|
179
183
|
"types": "./all.d.ts"
|
|
@@ -186,7 +190,7 @@
|
|
|
186
190
|
"README.md"
|
|
187
191
|
],
|
|
188
192
|
"dependencies": {
|
|
189
|
-
"@deepfuture/dui-core": "0.0.
|
|
193
|
+
"@deepfuture/dui-core": "0.0.17",
|
|
190
194
|
"lit": "^3.3.2",
|
|
191
195
|
"@lit/context": "^1.1.3"
|
|
192
196
|
},
|
package/popover/popover-popup.js
CHANGED
|
@@ -46,6 +46,10 @@ import { FloatingPortalController } from "@deepfuture/dui-core/floating-portal-c
|
|
|
46
46
|
import { renderArrow, } from "@deepfuture/dui-core/floating-popup-utils";
|
|
47
47
|
const hostStyles = css `
|
|
48
48
|
:host {
|
|
49
|
+
display: contents;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.slot-wrapper {
|
|
49
53
|
display: none;
|
|
50
54
|
}
|
|
51
55
|
`;
|
|
@@ -198,7 +202,7 @@ let DuiPopoverPopup = (() => {
|
|
|
198
202
|
this.#portal.offset = this.#ctx.value?.sideOffset ?? 8;
|
|
199
203
|
}
|
|
200
204
|
render() {
|
|
201
|
-
return html `<slot></slot>`;
|
|
205
|
+
return html `<div class="slot-wrapper"><slot></slot></div>`;
|
|
202
206
|
}
|
|
203
207
|
};
|
|
204
208
|
})();
|
|
@@ -46,6 +46,10 @@ import { FloatingPortalController } from "@deepfuture/dui-core/floating-portal-c
|
|
|
46
46
|
import { renderArrow, } from "@deepfuture/dui-core/floating-popup-utils";
|
|
47
47
|
const hostStyles = css `
|
|
48
48
|
:host {
|
|
49
|
+
display: contents;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.slot-wrapper {
|
|
49
53
|
display: none;
|
|
50
54
|
}
|
|
51
55
|
`;
|
|
@@ -186,7 +190,7 @@ let DuiPreviewCardPopup = (() => {
|
|
|
186
190
|
this.#portal.offset = this.#ctx.value?.sideOffset ?? 8;
|
|
187
191
|
}
|
|
188
192
|
render() {
|
|
189
|
-
return html `<slot></slot>`;
|
|
193
|
+
return html `<div class="slot-wrapper"><slot></slot></div>`;
|
|
190
194
|
}
|
|
191
195
|
};
|
|
192
196
|
})();
|
package/tabs/tabs-panel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Ported from original DUI: deep-future-app/app/client/components/dui/tabs */
|
|
2
|
-
import { LitElement,
|
|
2
|
+
import { LitElement, type TemplateResult } from "lit";
|
|
3
3
|
import { type TabsContext } from "./tabs-context.js";
|
|
4
4
|
/**
|
|
5
5
|
* Content panel for a tab. Shown when the matching tab is active.
|
|
@@ -14,5 +14,5 @@ export declare class DuiTabsPanel extends LitElement {
|
|
|
14
14
|
accessor keepMounted: boolean;
|
|
15
15
|
accessor _ctx: TabsContext;
|
|
16
16
|
willUpdate(): void;
|
|
17
|
-
render(): TemplateResult
|
|
17
|
+
render(): TemplateResult;
|
|
18
18
|
}
|
package/tabs/tabs-panel.js
CHANGED
|
@@ -43,7 +43,11 @@ const styles = css `
|
|
|
43
43
|
display: block;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
.wrapper {
|
|
47
|
+
display: contents;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.wrapper[hidden] {
|
|
47
51
|
display: none;
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -51,10 +55,6 @@ const styles = css `
|
|
|
51
55
|
position: relative;
|
|
52
56
|
outline: 0;
|
|
53
57
|
}
|
|
54
|
-
|
|
55
|
-
[part="panel"][hidden] {
|
|
56
|
-
display: none;
|
|
57
|
-
}
|
|
58
58
|
`;
|
|
59
59
|
/**
|
|
60
60
|
* Content panel for a tab. Shown when the matching tab is active.
|
|
@@ -107,17 +107,11 @@ let DuiTabsPanel = (() => {
|
|
|
107
107
|
}
|
|
108
108
|
render() {
|
|
109
109
|
const isActive = this.#isActive;
|
|
110
|
-
if (!isActive && !this.keepMounted) {
|
|
111
|
-
return nothing;
|
|
112
|
-
}
|
|
113
110
|
return html `
|
|
114
|
-
<div
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
tabindex="0"
|
|
119
|
-
>
|
|
120
|
-
<slot></slot>
|
|
111
|
+
<div class="wrapper" ?hidden=${!isActive}>
|
|
112
|
+
${isActive || this.keepMounted
|
|
113
|
+
? html `<div part="panel" role="tabpanel" tabindex="0"><slot></slot></div>`
|
|
114
|
+
: nothing}
|
|
121
115
|
</div>
|
|
122
116
|
`;
|
|
123
117
|
}
|
package/tooltip/tooltip-popup.js
CHANGED
|
@@ -46,6 +46,10 @@ import { FloatingPortalController } from "@deepfuture/dui-core/floating-portal-c
|
|
|
46
46
|
import { renderArrow, } from "@deepfuture/dui-core/floating-popup-utils";
|
|
47
47
|
const hostStyles = css `
|
|
48
48
|
:host {
|
|
49
|
+
display: contents;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.slot-wrapper {
|
|
49
53
|
display: none;
|
|
50
54
|
}
|
|
51
55
|
`;
|
|
@@ -178,7 +182,7 @@ let DuiTooltipPopup = (() => {
|
|
|
178
182
|
this.#portal.offset = this.#ctx.value?.sideOffset ?? 6;
|
|
179
183
|
}
|
|
180
184
|
render() {
|
|
181
|
-
return html `<slot></slot>`;
|
|
185
|
+
return html `<div class="slot-wrapper"><slot></slot></div>`;
|
|
182
186
|
}
|
|
183
187
|
};
|
|
184
188
|
})();
|