sliced-areas 1.0.2 → 1.0.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.
- package/README.md +39 -51
- package/dist/index.js +1 -1
- package/dist/{sliced-areas-DS_2BRnf.js → sliced-areas-rZ_V6Je7.js} +8 -3
- package/dist/sliced-areas-rZ_V6Je7.js.map +1 -0
- package/dist/sliced-areas.d.ts +8 -0
- package/dist/vue.d.ts +1 -0
- package/dist/vue.js +2 -2
- package/dist/vue.js.map +1 -1
- package/package.json +8 -5
- package/dist/sliced-areas-DS_2BRnf.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# sliced-areas
|
|
2
2
|
|
|
3
|
-
Blender-like
|
|
3
|
+
Blender-like resizable and splittable areas layout system. Available as a Web Component with optional Vue 3 wrapper.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
📚 **[Documentation & Examples](https://pavel-voronin.github.io/sliced-areas/)**
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
6
8
|
|
|
7
9
|
```sh
|
|
8
10
|
npm install sliced-areas
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
## Web Component
|
|
13
|
+
## Web Component Usage
|
|
12
14
|
|
|
13
15
|
```ts
|
|
14
16
|
import 'sliced-areas'
|
|
@@ -16,24 +18,28 @@ import 'sliced-areas/styles.css'
|
|
|
16
18
|
import type { AreasLayout, SlicedAreasElement } from 'sliced-areas'
|
|
17
19
|
|
|
18
20
|
const layout: AreasLayout = {
|
|
19
|
-
areas: [{ tag: 'viewport', rect: { left: 0, right: 1, top: 1, bottom: 0 } }]
|
|
21
|
+
areas: [{ tag: 'viewport', rect: { left: 0, right: 1, top: 1, bottom: 0 } }]
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const areas = document.querySelector('sliced-areas') as SlicedAreasElement
|
|
23
|
-
areas.setResolver((tag) =>
|
|
25
|
+
areas.setResolver((tag) => {
|
|
26
|
+
const div = document.createElement('div')
|
|
27
|
+
div.textContent = `Content for: ${tag}`
|
|
28
|
+
return div
|
|
29
|
+
})
|
|
24
30
|
areas.layout = layout
|
|
25
31
|
```
|
|
26
32
|
|
|
27
33
|
```html
|
|
28
|
-
<sliced-areas style="height:
|
|
29
|
-
<div data-area-tag="viewport">Viewport content</div>
|
|
34
|
+
<sliced-areas style="height: 100vh;"></sliced-areas>
|
|
30
35
|
```
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
**Important:** Resolver must return a fresh node each time. When areas share the same tag, reusing the same DOM element will move it to the last area.
|
|
38
|
+
|
|
39
|
+
## Vue 3 Usage
|
|
33
40
|
|
|
34
41
|
```ts
|
|
35
42
|
import { createApp } from 'vue'
|
|
36
|
-
import App from './App.vue'
|
|
37
43
|
import { SlicedAreasPlugin } from 'sliced-areas/vue'
|
|
38
44
|
import 'sliced-areas/styles.css'
|
|
39
45
|
|
|
@@ -43,21 +49,36 @@ app.mount('#app')
|
|
|
43
49
|
```
|
|
44
50
|
|
|
45
51
|
```vue
|
|
52
|
+
<script setup lang="ts">
|
|
53
|
+
import { ref } from 'vue'
|
|
54
|
+
import type { AreasLayout } from 'sliced-areas/vue'
|
|
55
|
+
|
|
56
|
+
const layout = ref<AreasLayout>({
|
|
57
|
+
areas: [{ tag: 'viewport', rect: { left: 0, right: 1, top: 1, bottom: 0 } }]
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const resolveArea = (tag: string) => {
|
|
61
|
+
const div = document.createElement('div')
|
|
62
|
+
div.textContent = `Content for: ${tag}`
|
|
63
|
+
return div
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const onLayoutChange = (detail: { layout: AreasLayout }) => {
|
|
67
|
+
layout.value = detail.layout
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
46
71
|
<template>
|
|
47
72
|
<SlicedAreas
|
|
48
|
-
class="layout-root"
|
|
49
73
|
:layout="layout"
|
|
50
74
|
:resolver="resolveArea"
|
|
51
75
|
@layoutchange="onLayoutChange"
|
|
52
|
-
@cornerclick="onCornerClick"
|
|
53
76
|
/>
|
|
54
77
|
</template>
|
|
55
78
|
```
|
|
56
79
|
|
|
57
80
|
## Layout Format
|
|
58
81
|
|
|
59
|
-
`AreasLayout` uses normalized coordinates (0..1) and tags for content lookup:
|
|
60
|
-
|
|
61
82
|
```ts
|
|
62
83
|
type AreasLayout = {
|
|
63
84
|
areas: Array<{
|
|
@@ -67,46 +88,13 @@ type AreasLayout = {
|
|
|
67
88
|
}
|
|
68
89
|
```
|
|
69
90
|
|
|
70
|
-
|
|
71
|
-
- The layout always fills the component bounds.
|
|
72
|
-
|
|
73
|
-
## Gestures and Operations
|
|
74
|
-
|
|
75
|
-
- Resize: drag splitters between areas.
|
|
76
|
-
- Move/Split/Join/Replace: drag an area corner into another area.
|
|
77
|
-
- Split orientation is inferred from drag direction.
|
|
78
|
-
- Swap: hold `Ctrl` while dragging an area into another.
|
|
79
|
-
- Maximize/Restore: use the API methods.
|
|
91
|
+
Coordinates are normalized (0 to 1). `top: 1` is top edge, `bottom: 0` is bottom edge.
|
|
80
92
|
|
|
81
93
|
## Events
|
|
82
94
|
|
|
83
|
-
- `sliced-areas:layoutchange`
|
|
84
|
-
- `sliced-areas:cornerclick`
|
|
95
|
+
- `sliced-areas:layoutchange` / `@layoutchange` - Fired when layout changes
|
|
96
|
+
- `sliced-areas:cornerclick` / `@cornerclick` - Fired when corner is clicked
|
|
85
97
|
|
|
86
|
-
|
|
98
|
+
## License
|
|
87
99
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
```ts
|
|
91
|
-
element.layout: AreasLayout | null
|
|
92
|
-
element.setResolver(resolver: (tag: string) => HTMLElement | null | undefined): void
|
|
93
|
-
element.split(areaId, zone?, clientX?, clientY?): void
|
|
94
|
-
element.join(sourceAreaId, targetAreaId): void
|
|
95
|
-
element.replace(sourceAreaId, targetAreaId): void
|
|
96
|
-
element.swap(sourceAreaId, targetAreaId): void
|
|
97
|
-
element.move(sourceAreaId, targetAreaId, overlayRect, remainderRect): void
|
|
98
|
-
element.close(areaId): void
|
|
99
|
-
element.retag(areaId, tag): void
|
|
100
|
-
element.maximize(areaId): void
|
|
101
|
-
element.restore(): void
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Retagging from Area Content
|
|
105
|
-
|
|
106
|
-
Dispatch a bubbling event from inside an area node to update its tag:
|
|
107
|
-
|
|
108
|
-
```ts
|
|
109
|
-
node.dispatchEvent(
|
|
110
|
-
new CustomEvent('sliced-areas:retag', { bubbles: true, detail: { tag: 'viewport' } }),
|
|
111
|
-
)
|
|
112
|
-
```
|
|
100
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as registerSlicedAreasElement, t as SlicedAreasElement } from "./sliced-areas-
|
|
1
|
+
import { n as registerSlicedAreasElement, t as SlicedAreasElement } from "./sliced-areas-rZ_V6Je7.js";
|
|
2
2
|
export { SlicedAreasElement, registerSlicedAreasElement };
|
|
@@ -122,7 +122,7 @@ var INTERNAL_ATTR = "data-sliced-areas-internal", AUTO_ATTR = "data-sliced-areas
|
|
|
122
122
|
continue;
|
|
123
123
|
}
|
|
124
124
|
let i = this.areaTags.get(e.id) ?? e.id, a = this.areaResolver(i);
|
|
125
|
-
a && (a.dataset.areaId = e.id, a.setAttribute(AUTO_ATTR, "true"), this.resolvedNodes.set(e.id, a), n.set(e.id, a));
|
|
125
|
+
a && (this.assertFreshResolvedNode(e.id, i, a), a.dataset.areaId = e.id, a.setAttribute(AUTO_ATTR, "true"), this.resolvedNodes.set(e.id, a), n.set(e.id, a));
|
|
126
126
|
}
|
|
127
127
|
r = Object.values(this.graph.areas).filter((e) => !n.has(e.id));
|
|
128
128
|
}
|
|
@@ -177,6 +177,11 @@ var INTERNAL_ATTR = "data-sliced-areas-internal", AUTO_ATTR = "data-sliced-areas
|
|
|
177
177
|
}
|
|
178
178
|
return n;
|
|
179
179
|
}
|
|
180
|
+
assertFreshResolvedNode(e, t, n) {
|
|
181
|
+
let r = n.dataset.areaId;
|
|
182
|
+
if (r && r !== e) throw Error(`Resolver must return a fresh element per area. Got an element already assigned to "${r}" for tag "${t}".`);
|
|
183
|
+
for (let [r, i] of this.resolvedNodes.entries()) if (i === n && r !== e) throw Error(`Resolver must return a fresh element per area. Got the same element for "${r}" and "${e}" (tag "${t}").`);
|
|
184
|
+
}
|
|
180
185
|
ensureAreaNode(n, r, i = !0) {
|
|
181
186
|
if (Array.from(this.querySelectorAll(`[data-area-id="${n}"]`)).find((t) => !t.hasAttribute(INTERNAL_ATTR))) return;
|
|
182
187
|
this.inheritAreaTag(n, r);
|
|
@@ -189,7 +194,7 @@ var INTERNAL_ATTR = "data-sliced-areas-internal", AUTO_ATTR = "data-sliced-areas
|
|
|
189
194
|
if (a && this.areaResolver) {
|
|
190
195
|
let e = this.areaResolver(a);
|
|
191
196
|
if (e) {
|
|
192
|
-
e.dataset.areaId = n, e.setAttribute(AUTO_ATTR, "true"), this.appendChild(e);
|
|
197
|
+
this.assertFreshResolvedNode(n, a, e), e.dataset.areaId = n, e.setAttribute(AUTO_ATTR, "true"), this.appendChild(e);
|
|
193
198
|
return;
|
|
194
199
|
}
|
|
195
200
|
}
|
|
@@ -1732,4 +1737,4 @@ const registerSlicedAreasElement = () => {
|
|
|
1732
1737
|
registerSlicedAreasElement();
|
|
1733
1738
|
export { registerSlicedAreasElement as n, SlicedAreasElement as t };
|
|
1734
1739
|
|
|
1735
|
-
//# sourceMappingURL=sliced-areas-
|
|
1740
|
+
//# sourceMappingURL=sliced-areas-rZ_V6Je7.js.map
|