@adia-ai/web-modules 0.3.5 → 0.3.6
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/CHANGELOG.md +26 -0
- package/editor/editor-canvas/editor-canvas.a2ui.json +87 -0
- package/editor/editor-canvas/editor-canvas.js +103 -0
- package/editor/editor-canvas/editor-canvas.test.js +100 -0
- package/editor/editor-canvas/editor-canvas.yaml +88 -0
- package/editor/editor-canvas-empty/editor-canvas-empty.a2ui.json +69 -0
- package/editor/editor-canvas-empty/editor-canvas-empty.yaml +56 -0
- package/editor/editor-shell/css/editor-shell.bespoke.css +172 -0
- package/editor/editor-shell/editor-shell.css +1 -0
- package/editor/editor-shell/editor-shell.js +85 -30
- package/editor/editor-sidebar/editor-sidebar.a2ui.json +88 -0
- package/editor/editor-sidebar/editor-sidebar.js +173 -0
- package/editor/editor-sidebar/editor-sidebar.test.js +126 -0
- package/editor/editor-sidebar/editor-sidebar.yaml +83 -0
- package/editor/editor-statusbar/editor-statusbar.a2ui.json +76 -0
- package/editor/editor-statusbar/editor-statusbar.yaml +57 -0
- package/editor/editor-toolbar/editor-toolbar.a2ui.json +96 -0
- package/editor/editor-toolbar/editor-toolbar.js +58 -0
- package/editor/editor-toolbar/editor-toolbar.test.js +99 -0
- package/editor/editor-toolbar/editor-toolbar.yaml +81 -0
- package/editor/index.js +3 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,32 @@ Built from `@adia-ai/web-components` primitives.
|
|
|
11
11
|
|
|
12
12
|
_No pending changes._
|
|
13
13
|
|
|
14
|
+
## [0.3.6] - 2026-05-10
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Editor cluster bespoke family** — third cluster decomposed per ADR-0023, confirming the pattern is canonical across 3 distinct shell archetypes.
|
|
19
|
+
- **`<editor-toolbar full-screen?>`** — JS-bearing (58 LOC + 8 unit tests). Replaces legacy `<header>` chrome bar inside `<editor-shell>`. Click-bubble for `[data-toolbar-action]` fires `toolbar-action` event. Slot vocabulary (title, status, action, action-leading).
|
|
20
|
+
- **`<editor-canvas empty? focused?>`** — JS-bearing (103 LOC + 11 unit tests). Replaces legacy `<div data-canvas>`. Owns scroll/zoom container, `[empty]` reflected, `[focused]` reflected. Public API: `.focus()` / `.blur()` / `.resetView()` / `.zoom` getter+setter.
|
|
21
|
+
- **`<editor-sidebar collapsible>`** — JS-bearing (170 LOC + 11 unit tests). **First bespoke child that DELEGATES rather than DUPLICATES a primitive's behavior** — wraps `<pane-ui resizable>` for drag, owns `[collapsed]` reflected via ResizeObserver, localStorage persistence (`adia-editor-sidebar-{name}` cluster-distinct).
|
|
22
|
+
- **2 CSS-only structural children** — `<editor-statusbar>`, `<editor-canvas-empty>` (visibility driven by parent `<editor-canvas>[empty]`).
|
|
23
|
+
|
|
24
|
+
- **CSS bridge** `editor/editor-shell/css/editor-shell.bespoke.css` (172 LOC) — maps the 5 bespoke editor tags to a CSS Grid layout. Imported last in `editor-shell.css`.
|
|
25
|
+
|
|
26
|
+
- **`editor/index.js` exports** all 4 JS-bearing editor children (EditorShell + EditorToolbar + EditorCanvas + EditorSidebar). Subpath import unchanged: `import '@adia-ai/web-modules/editor'`.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **`<editor-shell>` host** — refactored from 56 LOC (just select-options JSON parsing) to 115 LOC. Reads BOTH legacy + bespoke shapes via priority chain. Adds `[focus-mode]` reflected attribute that propagates to bespoke children's `[full-screen]` / `[focused]`. Listens for `toolbar-action` bubble events. Backwards compat preserved.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **`<editor-sidebar>.collapse()` persist-before-snap bug** (commit `1d63f0d1`) — the implementation was setting `style.width = SNAP_THRESHOLD` THEN calling `#persistWidth()`, which overwrote storage with 96 (the snap value). On `expand()` the stored value would be ≤ threshold and fall through to default 240, losing the user's pre-collapse width. Fix: capture pre-collapse width by calling `#persistWidth()` BEFORE the snap, guarded by `if (!this.collapsed)`. Caught by the `expand() restores from stored width or defaults to 240` test on first run. Documented as Pitfall #12 in the `bespoke-shell-children` skill.
|
|
35
|
+
|
|
36
|
+
### Backwards compatibility
|
|
37
|
+
|
|
38
|
+
Legacy authoring shapes (`<header>`, `<div data-editor-body>`, `<pane-ui data-left|data-right>`, `<div data-canvas>`, `<footer>`) all still work identically. Mixed markup renders the same. Migration is opt-in.
|
|
39
|
+
|
|
14
40
|
## [0.3.5] - 2026-05-07
|
|
15
41
|
|
|
16
42
|
### Added
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/EditorCanvas.json",
|
|
4
|
+
"title": "EditorCanvas",
|
|
5
|
+
"description": "Module-tier editor canvas surface — replaces legacy <div data-canvas>\ninside <editor-shell> per ADR-0023. Owns scroll/zoom container\nsemantics, [empty] and [focused] reflected attributes, and a stable\ntarget for the host's content rendering pipeline.\n\nSits as the central content region inside <editor-shell>, between\nthe optional <editor-sidebar slot=\"leading\"> and <editor-sidebar\nslot=\"trailing\">. Authors compose <editor-canvas-empty> as an\noptional first child for the empty state; canvas content children\n(artboards, document body, etc.) are appended either statically or\ndynamically by the host.\n\nBackwards compat — <editor-shell> still recognizes the legacy\n<div data-canvas> shape via :is() selector. New code should prefer\n<editor-canvas>.\n",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "EditorCanvas"
|
|
18
|
+
},
|
|
19
|
+
"empty": {
|
|
20
|
+
"description": "Reflected — set when zero non-<editor-canvas-empty> children.\nDrives the <editor-canvas-empty> visibility via parent CSS —\nno JS toggling needed.\n",
|
|
21
|
+
"type": "boolean",
|
|
22
|
+
"default": true
|
|
23
|
+
},
|
|
24
|
+
"focused": {
|
|
25
|
+
"description": "Reflected — set when canvas claims focus ownership (programmatic\n.focus() call or toolbar full-screen toggle).\n",
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": false
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"required": [
|
|
31
|
+
"component"
|
|
32
|
+
],
|
|
33
|
+
"unevaluatedProperties": false,
|
|
34
|
+
"x-adiaui": {
|
|
35
|
+
"anti_patterns": [],
|
|
36
|
+
"category": "container",
|
|
37
|
+
"events": {},
|
|
38
|
+
"examples": [],
|
|
39
|
+
"keywords": [
|
|
40
|
+
"editor-canvas",
|
|
41
|
+
"canvas",
|
|
42
|
+
"workspace",
|
|
43
|
+
"artboard",
|
|
44
|
+
"editor-surface"
|
|
45
|
+
],
|
|
46
|
+
"name": "EditorCanvas",
|
|
47
|
+
"related": [
|
|
48
|
+
"EditorShell",
|
|
49
|
+
"EditorCanvasEmpty",
|
|
50
|
+
"EditorToolbar",
|
|
51
|
+
"EditorSidebar"
|
|
52
|
+
],
|
|
53
|
+
"slots": {
|
|
54
|
+
"default": {
|
|
55
|
+
"description": "Default — canvas content (artboards, document body, blocks, etc.) plus an optional first <editor-canvas-empty> sibling for the empty state."
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"states": [
|
|
59
|
+
{
|
|
60
|
+
"description": "Default canvas mode.",
|
|
61
|
+
"name": "idle"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"description": "Zero content children — empty state visible.",
|
|
65
|
+
"attribute": "empty",
|
|
66
|
+
"name": "empty"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"description": "Canvas is the focus surface.",
|
|
70
|
+
"attribute": "focused",
|
|
71
|
+
"name": "focused"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"synonyms": {
|
|
75
|
+
"editor-canvas": [
|
|
76
|
+
"canvas",
|
|
77
|
+
"workspace",
|
|
78
|
+
"artboard",
|
|
79
|
+
"design-surface"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
"tag": "editor-canvas",
|
|
83
|
+
"tokens": {},
|
|
84
|
+
"traits": [],
|
|
85
|
+
"version": 1
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* <editor-canvas focused?>
|
|
3
|
+
* <editor-canvas-empty>...</editor-canvas-empty> (optional empty state)
|
|
4
|
+
* <!-- canvas content (children) -->
|
|
5
|
+
* </editor-canvas>
|
|
6
|
+
*
|
|
7
|
+
* Module-tier editor canvas surface — replaces legacy <div data-canvas>
|
|
8
|
+
* inside <editor-shell> per ADR-0023. Owns:
|
|
9
|
+
*
|
|
10
|
+
* - [empty] reflected attribute (set when no non-stub children) —
|
|
11
|
+
* drives <editor-canvas-empty> visibility via parent CSS
|
|
12
|
+
* - [focused] reflected attribute (set when canvas claims focus
|
|
13
|
+
* ownership; e.g., toolbar full-screen toggle, click-to-focus)
|
|
14
|
+
* - Public API for zoom/pan refs (.zoom getter/setter, .resetView())
|
|
15
|
+
* - .focus() / .blur() programmatic — sets [focused] reflected
|
|
16
|
+
*
|
|
17
|
+
* Reflected attributes:
|
|
18
|
+
* [empty] — true when zero non-<editor-canvas-empty> children
|
|
19
|
+
* [focused] — true when canvas is the focus surface
|
|
20
|
+
*
|
|
21
|
+
* Public methods:
|
|
22
|
+
* .focus() — claim focus + reflect [focused]
|
|
23
|
+
* .blur() — release focus + clear [focused]
|
|
24
|
+
* .resetView() — reset zoom/pan to defaults
|
|
25
|
+
*
|
|
26
|
+
* Properties:
|
|
27
|
+
* .zoom — getter/setter (default 1.0)
|
|
28
|
+
*
|
|
29
|
+
* The host (<editor-shell>) reads either <editor-canvas> or
|
|
30
|
+
* [data-canvas] / <div data-canvas> via :is() selector for backwards
|
|
31
|
+
* compat.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { UIElement } from '../../../web-components/core/element.js';
|
|
35
|
+
|
|
36
|
+
class EditorCanvas extends UIElement {
|
|
37
|
+
static properties = {
|
|
38
|
+
empty: { type: Boolean, default: true, reflect: true },
|
|
39
|
+
focused: { type: Boolean, default: false, reflect: true },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
static template = () => null;
|
|
43
|
+
|
|
44
|
+
#zoom = 1.0;
|
|
45
|
+
#childObserver = null;
|
|
46
|
+
|
|
47
|
+
connected() {
|
|
48
|
+
this.#syncEmptyFromChildren();
|
|
49
|
+
this.#setupChildObserver();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
disconnected() {
|
|
53
|
+
this.#childObserver?.disconnect();
|
|
54
|
+
this.#childObserver = null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Public API ──
|
|
58
|
+
|
|
59
|
+
get zoom() {
|
|
60
|
+
return this.#zoom;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
set zoom(value) {
|
|
64
|
+
const v = parseFloat(value);
|
|
65
|
+
if (!isFinite(v) || v <= 0) return;
|
|
66
|
+
this.#zoom = v;
|
|
67
|
+
this.style.setProperty('--editor-canvas-zoom', String(v));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
resetView() {
|
|
71
|
+
this.zoom = 1.0;
|
|
72
|
+
// Future: also reset pan offsets when implemented
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
focus() {
|
|
76
|
+
super.focus?.();
|
|
77
|
+
this.focused = true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
blur() {
|
|
81
|
+
super.blur?.();
|
|
82
|
+
this.focused = false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── Internal: empty state from children ──
|
|
86
|
+
|
|
87
|
+
#syncEmptyFromChildren() {
|
|
88
|
+
const contentChildren = Array.from(this.children).filter(
|
|
89
|
+
(c) => c.tagName.toLowerCase() !== 'editor-canvas-empty'
|
|
90
|
+
);
|
|
91
|
+
this.empty = contentChildren.length === 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#setupChildObserver() {
|
|
95
|
+
this.#childObserver = new MutationObserver(() => {
|
|
96
|
+
this.#syncEmptyFromChildren();
|
|
97
|
+
});
|
|
98
|
+
this.#childObserver.observe(this, { childList: true });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
customElements.define('editor-canvas', EditorCanvas);
|
|
103
|
+
export { EditorCanvas };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import '../../../web-components/core/element.js';
|
|
3
|
+
import './editor-canvas.js';
|
|
4
|
+
|
|
5
|
+
const tick = () => new Promise((r) => queueMicrotask(r));
|
|
6
|
+
|
|
7
|
+
function mount(html) {
|
|
8
|
+
const wrap = document.createElement('div');
|
|
9
|
+
wrap.innerHTML = html;
|
|
10
|
+
document.body.appendChild(wrap);
|
|
11
|
+
return wrap.firstElementChild;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
document.body.innerHTML = '';
|
|
16
|
+
globalThis.MutationObserver = class {
|
|
17
|
+
observe() {} disconnect() {}
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
describe('editor-canvas', () => {
|
|
22
|
+
it('registers editor-canvas as a custom element', () => {
|
|
23
|
+
expect(customElements.get('editor-canvas')).toBeDefined();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('defaults to focused=false', () => {
|
|
27
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
28
|
+
expect(c.focused).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('defaults to empty=true with no children', async () => {
|
|
32
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
33
|
+
await tick();
|
|
34
|
+
expect(c.empty).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('reflects [empty] via property assignment', async () => {
|
|
38
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
39
|
+
c.empty = false;
|
|
40
|
+
await tick();
|
|
41
|
+
expect(c.hasAttribute('empty')).toBe(false);
|
|
42
|
+
c.empty = true;
|
|
43
|
+
await tick();
|
|
44
|
+
expect(c.hasAttribute('empty')).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('reflects [focused] via property assignment', async () => {
|
|
48
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
49
|
+
c.focused = true;
|
|
50
|
+
await tick();
|
|
51
|
+
expect(c.hasAttribute('focused')).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('does not count <editor-canvas-empty> stub as a content child', () => {
|
|
55
|
+
const c = mount('<editor-canvas><editor-canvas-empty></editor-canvas-empty></editor-canvas>');
|
|
56
|
+
expect(c.empty).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('exposes .zoom getter/setter (default 1.0)', () => {
|
|
60
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
61
|
+
expect(c.zoom).toBe(1.0);
|
|
62
|
+
c.zoom = 2.0;
|
|
63
|
+
expect(c.zoom).toBe(2.0);
|
|
64
|
+
expect(c.style.getPropertyValue('--editor-canvas-zoom')).toBe('2');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('rejects invalid zoom values', () => {
|
|
68
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
69
|
+
c.zoom = 1.5;
|
|
70
|
+
c.zoom = 'invalid'; // should not change
|
|
71
|
+
expect(c.zoom).toBe(1.5);
|
|
72
|
+
c.zoom = -1; // should not change
|
|
73
|
+
expect(c.zoom).toBe(1.5);
|
|
74
|
+
c.zoom = 0; // should not change
|
|
75
|
+
expect(c.zoom).toBe(1.5);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('.resetView() restores zoom to 1.0', () => {
|
|
79
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
80
|
+
c.zoom = 2.5;
|
|
81
|
+
c.resetView();
|
|
82
|
+
expect(c.zoom).toBe(1.0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('.focus() sets [focused] reflected', async () => {
|
|
86
|
+
const c = mount('<editor-canvas></editor-canvas>');
|
|
87
|
+
c.focus();
|
|
88
|
+
await tick();
|
|
89
|
+
expect(c.focused).toBe(true);
|
|
90
|
+
expect(c.hasAttribute('focused')).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('.blur() clears [focused] reflected', async () => {
|
|
94
|
+
const c = mount('<editor-canvas focused></editor-canvas>');
|
|
95
|
+
c.blur();
|
|
96
|
+
await tick();
|
|
97
|
+
expect(c.focused).toBe(false);
|
|
98
|
+
expect(c.hasAttribute('focused')).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
3
|
+
name: EditorCanvas
|
|
4
|
+
tag: editor-canvas
|
|
5
|
+
component: EditorCanvas
|
|
6
|
+
category: container
|
|
7
|
+
version: 1
|
|
8
|
+
description: |
|
|
9
|
+
Module-tier editor canvas surface — replaces legacy <div data-canvas>
|
|
10
|
+
inside <editor-shell> per ADR-0023. Owns scroll/zoom container
|
|
11
|
+
semantics, [empty] and [focused] reflected attributes, and a stable
|
|
12
|
+
target for the host's content rendering pipeline.
|
|
13
|
+
|
|
14
|
+
Sits as the central content region inside <editor-shell>, between
|
|
15
|
+
the optional <editor-sidebar slot="leading"> and <editor-sidebar
|
|
16
|
+
slot="trailing">. Authors compose <editor-canvas-empty> as an
|
|
17
|
+
optional first child for the empty state; canvas content children
|
|
18
|
+
(artboards, document body, etc.) are appended either statically or
|
|
19
|
+
dynamically by the host.
|
|
20
|
+
|
|
21
|
+
Backwards compat — <editor-shell> still recognizes the legacy
|
|
22
|
+
<div data-canvas> shape via :is() selector. New code should prefer
|
|
23
|
+
<editor-canvas>.
|
|
24
|
+
|
|
25
|
+
props:
|
|
26
|
+
empty:
|
|
27
|
+
description: |
|
|
28
|
+
Reflected — set when zero non-<editor-canvas-empty> children.
|
|
29
|
+
Drives the <editor-canvas-empty> visibility via parent CSS —
|
|
30
|
+
no JS toggling needed.
|
|
31
|
+
type: boolean
|
|
32
|
+
default: true
|
|
33
|
+
reflect: true
|
|
34
|
+
focused:
|
|
35
|
+
description: |
|
|
36
|
+
Reflected — set when canvas claims focus ownership (programmatic
|
|
37
|
+
.focus() call or toolbar full-screen toggle).
|
|
38
|
+
type: boolean
|
|
39
|
+
default: false
|
|
40
|
+
reflect: true
|
|
41
|
+
|
|
42
|
+
events: {}
|
|
43
|
+
|
|
44
|
+
slots:
|
|
45
|
+
default:
|
|
46
|
+
description: >-
|
|
47
|
+
Default — canvas content (artboards, document body, blocks, etc.)
|
|
48
|
+
plus an optional first <editor-canvas-empty> sibling for the
|
|
49
|
+
empty state.
|
|
50
|
+
|
|
51
|
+
states:
|
|
52
|
+
- name: idle
|
|
53
|
+
description: Default canvas mode.
|
|
54
|
+
- name: empty
|
|
55
|
+
attribute: empty
|
|
56
|
+
description: Zero content children — empty state visible.
|
|
57
|
+
- name: focused
|
|
58
|
+
attribute: focused
|
|
59
|
+
description: Canvas is the focus surface.
|
|
60
|
+
|
|
61
|
+
traits: []
|
|
62
|
+
|
|
63
|
+
a2ui:
|
|
64
|
+
rules:
|
|
65
|
+
- >-
|
|
66
|
+
editor-canvas is the bespoke replacement for legacy
|
|
67
|
+
<div data-canvas> inside <editor-shell>. Use it as the central
|
|
68
|
+
content region for editor work surfaces.
|
|
69
|
+
- >-
|
|
70
|
+
Place <editor-canvas-empty> as an optional first child for the
|
|
71
|
+
empty state; the [empty] reflected attribute drives its visibility
|
|
72
|
+
via CSS (no JS toggling).
|
|
73
|
+
|
|
74
|
+
keywords:
|
|
75
|
+
- editor-canvas
|
|
76
|
+
- canvas
|
|
77
|
+
- workspace
|
|
78
|
+
- artboard
|
|
79
|
+
- editor-surface
|
|
80
|
+
|
|
81
|
+
synonyms:
|
|
82
|
+
editor-canvas: [canvas, workspace, artboard, design-surface]
|
|
83
|
+
|
|
84
|
+
related:
|
|
85
|
+
- EditorShell
|
|
86
|
+
- EditorCanvasEmpty
|
|
87
|
+
- EditorToolbar
|
|
88
|
+
- EditorSidebar
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/EditorCanvasEmpty.json",
|
|
4
|
+
"title": "EditorCanvasEmpty",
|
|
5
|
+
"description": "Module-tier editor canvas empty state. CSS-only — no behavior, no\nJS. Sits as the first child of <editor-canvas> as the empty state\nplaceholder. Visibility is driven by <editor-canvas>'s [empty]\nreflected attribute via CSS (no JS toggling) — when content arrives,\nthe parent canvas loses [empty] and CSS hides this stub.\n\nReplaces ad-hoc empty-state placement inside the legacy\n<div data-canvas> per ADR-0023.\n",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "EditorCanvasEmpty"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": [
|
|
21
|
+
"component"
|
|
22
|
+
],
|
|
23
|
+
"unevaluatedProperties": false,
|
|
24
|
+
"x-adiaui": {
|
|
25
|
+
"anti_patterns": [],
|
|
26
|
+
"category": "feedback",
|
|
27
|
+
"events": {},
|
|
28
|
+
"examples": [],
|
|
29
|
+
"keywords": [
|
|
30
|
+
"editor-canvas-empty",
|
|
31
|
+
"empty-state",
|
|
32
|
+
"placeholder",
|
|
33
|
+
"no-content",
|
|
34
|
+
"canvas-empty"
|
|
35
|
+
],
|
|
36
|
+
"name": "EditorCanvasEmpty",
|
|
37
|
+
"related": [
|
|
38
|
+
"EditorShell",
|
|
39
|
+
"EditorCanvas",
|
|
40
|
+
"EmptyState"
|
|
41
|
+
],
|
|
42
|
+
"slots": {
|
|
43
|
+
"default": {
|
|
44
|
+
"description": "Empty state content — typically <empty-state-ui> with a \"Create new...\" prompt or onboarding affordance."
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"states": [
|
|
48
|
+
{
|
|
49
|
+
"description": "Default, visible.",
|
|
50
|
+
"name": "idle"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"description": "Hidden via parent <editor-canvas>:not([empty]) selector.",
|
|
54
|
+
"name": "hidden"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"synonyms": {
|
|
58
|
+
"editor-canvas-empty": [
|
|
59
|
+
"empty-state",
|
|
60
|
+
"placeholder",
|
|
61
|
+
"no-document"
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"tag": "editor-canvas-empty",
|
|
65
|
+
"tokens": {},
|
|
66
|
+
"traits": [],
|
|
67
|
+
"version": 1
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
3
|
+
name: EditorCanvasEmpty
|
|
4
|
+
tag: editor-canvas-empty
|
|
5
|
+
component: EditorCanvasEmpty
|
|
6
|
+
category: feedback
|
|
7
|
+
version: 1
|
|
8
|
+
description: |
|
|
9
|
+
Module-tier editor canvas empty state. CSS-only — no behavior, no
|
|
10
|
+
JS. Sits as the first child of <editor-canvas> as the empty state
|
|
11
|
+
placeholder. Visibility is driven by <editor-canvas>'s [empty]
|
|
12
|
+
reflected attribute via CSS (no JS toggling) — when content arrives,
|
|
13
|
+
the parent canvas loses [empty] and CSS hides this stub.
|
|
14
|
+
|
|
15
|
+
Replaces ad-hoc empty-state placement inside the legacy
|
|
16
|
+
<div data-canvas> per ADR-0023.
|
|
17
|
+
|
|
18
|
+
props: {}
|
|
19
|
+
|
|
20
|
+
events: {}
|
|
21
|
+
|
|
22
|
+
slots:
|
|
23
|
+
default:
|
|
24
|
+
description: >-
|
|
25
|
+
Empty state content — typically <empty-state-ui> with a
|
|
26
|
+
"Create new..." prompt or onboarding affordance.
|
|
27
|
+
|
|
28
|
+
states:
|
|
29
|
+
- name: idle
|
|
30
|
+
description: Default, visible.
|
|
31
|
+
- name: hidden
|
|
32
|
+
description: Hidden via parent <editor-canvas>:not([empty]) selector.
|
|
33
|
+
|
|
34
|
+
traits: []
|
|
35
|
+
|
|
36
|
+
a2ui:
|
|
37
|
+
rules:
|
|
38
|
+
- >-
|
|
39
|
+
editor-canvas-empty is the bespoke empty-state slot for
|
|
40
|
+
<editor-canvas>. Place as the first child of <editor-canvas>;
|
|
41
|
+
visibility is automatic via the [empty] reflected attribute.
|
|
42
|
+
|
|
43
|
+
keywords:
|
|
44
|
+
- editor-canvas-empty
|
|
45
|
+
- empty-state
|
|
46
|
+
- placeholder
|
|
47
|
+
- no-content
|
|
48
|
+
- canvas-empty
|
|
49
|
+
|
|
50
|
+
synonyms:
|
|
51
|
+
editor-canvas-empty: [empty-state, placeholder, no-document]
|
|
52
|
+
|
|
53
|
+
related:
|
|
54
|
+
- EditorShell
|
|
55
|
+
- EditorCanvas
|
|
56
|
+
- EmptyState
|