ember-primitives 0.60.1 → 0.61.1
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 +9 -9
- package/declarations/components/resizable/state.d.ts +31 -0
- package/declarations/components/resizable/state.d.ts.map +1 -0
- package/declarations/components/resizable.d.ts +98 -0
- package/declarations/components/resizable.d.ts.map +1 -0
- package/declarations/dom-context.d.ts +6 -3
- package/declarations/dom-context.d.ts.map +1 -1
- package/declarations/index.d.ts +1 -0
- package/declarations/index.d.ts.map +1 -1
- package/dist/components/resizable/state.js +631 -0
- package/dist/components/resizable/state.js.map +1 -0
- package/dist/components/resizable.css +40 -0
- package/dist/components/resizable.js +82 -0
- package/dist/components/resizable.js.map +1 -0
- package/dist/dom-context.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/resizable/state.ts +815 -0
- package/src/components/resizable.css +40 -0
- package/src/components/resizable.gts +171 -0
- package/src/dom-context.gts +6 -3
- package/src/index.ts +5 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
.ember-primitives__resizable {
|
|
2
|
+
display: flex;
|
|
3
|
+
width: 100%;
|
|
4
|
+
height: 100%;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.ember-primitives__resizable[data-orientation="horizontal"] {
|
|
9
|
+
flex-direction: row;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.ember-primitives__resizable[data-orientation="vertical"] {
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.ember-primitives__resizable__panel {
|
|
17
|
+
/* until the group assigns sizes, share space equally */
|
|
18
|
+
flex: 1 1 0px;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
min-height: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.ember-primitives__resizable__handle {
|
|
25
|
+
flex: 0 0 auto;
|
|
26
|
+
position: relative;
|
|
27
|
+
touch-action: none;
|
|
28
|
+
user-select: none;
|
|
29
|
+
-webkit-user-select: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.ember-primitives__resizable__handle[data-orientation="horizontal"] {
|
|
33
|
+
width: 0.5rem;
|
|
34
|
+
cursor: col-resize;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.ember-primitives__resizable__handle[data-orientation="vertical"] {
|
|
38
|
+
height: 0.5rem;
|
|
39
|
+
cursor: row-resize;
|
|
40
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import "./resizable.css";
|
|
2
|
+
|
|
3
|
+
import Component from "@glimmer/component";
|
|
4
|
+
import { on } from "@ember/modifier";
|
|
5
|
+
|
|
6
|
+
import { modifier } from "ember-modifier";
|
|
7
|
+
|
|
8
|
+
import { Consume, Provide } from "../dom-context.gts";
|
|
9
|
+
import { GroupState } from "./resizable/state.ts";
|
|
10
|
+
|
|
11
|
+
import type { Orientation } from "./resizable/state.ts";
|
|
12
|
+
import type { TOC } from "@ember/component/template-only";
|
|
13
|
+
|
|
14
|
+
export type { Orientation };
|
|
15
|
+
|
|
16
|
+
export interface PanelSignature {
|
|
17
|
+
Element: HTMLDivElement;
|
|
18
|
+
Args: {
|
|
19
|
+
/**
|
|
20
|
+
* The smallest size (in % of the group) this panel may be resized to.
|
|
21
|
+
* Defaults to 0.
|
|
22
|
+
*/
|
|
23
|
+
minSize?: number;
|
|
24
|
+
/**
|
|
25
|
+
* The largest size (in % of the group) this panel may be resized to.
|
|
26
|
+
* Defaults to 100.
|
|
27
|
+
*/
|
|
28
|
+
maxSize?: number;
|
|
29
|
+
/**
|
|
30
|
+
* The initial size (in % of the group).
|
|
31
|
+
* Panels without a size share the remaining space equally.
|
|
32
|
+
*/
|
|
33
|
+
size?: number;
|
|
34
|
+
/**
|
|
35
|
+
* When true, pressing Enter on the handle after this panel
|
|
36
|
+
* collapses the panel to 0 (and restores it on the next press),
|
|
37
|
+
* and dragging well past `@minSize` snaps it closed.
|
|
38
|
+
*
|
|
39
|
+
* While collapsed, the panel has a `data-collapsed` attribute.
|
|
40
|
+
*/
|
|
41
|
+
collapsible?: boolean;
|
|
42
|
+
};
|
|
43
|
+
Blocks: {
|
|
44
|
+
default: [];
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A resizable region within a `<Resizable>` group.
|
|
50
|
+
*
|
|
51
|
+
* Panels declare their constraints as data attributes, so the group
|
|
52
|
+
* discovers them with DOM queries -- there is no registration, and a
|
|
53
|
+
* Panel may contain another `<Resizable>` to nest layouts.
|
|
54
|
+
*/
|
|
55
|
+
let panelId = 0;
|
|
56
|
+
|
|
57
|
+
function nextPanelId(): string {
|
|
58
|
+
return `ember-primitives__resizable__panel--${panelId++}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const Panel: TOC<PanelSignature> = <template>
|
|
62
|
+
<div
|
|
63
|
+
class="ember-primitives__resizable__panel"
|
|
64
|
+
data-min-size={{@minSize}}
|
|
65
|
+
data-max-size={{@maxSize}}
|
|
66
|
+
data-size={{@size}}
|
|
67
|
+
data-collapsible={{if @collapsible "true"}}
|
|
68
|
+
...attributes
|
|
69
|
+
{{! after ...attributes: the id is component-owned (the handles'
|
|
70
|
+
aria-controls depends on it being present and unique) }}
|
|
71
|
+
id={{(nextPanelId)}}
|
|
72
|
+
>
|
|
73
|
+
{{yield}}
|
|
74
|
+
</div>
|
|
75
|
+
</template>;
|
|
76
|
+
|
|
77
|
+
export interface HandleSignature {
|
|
78
|
+
Element: HTMLDivElement;
|
|
79
|
+
Blocks: {
|
|
80
|
+
default: [];
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function onPointerDown(state: GroupState) {
|
|
85
|
+
return (event: PointerEvent) => state.startDrag(event.currentTarget as HTMLElement, event);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function onKeyDown(state: GroupState) {
|
|
89
|
+
return (event: KeyboardEvent) => state.handleKeyDown(event.currentTarget as HTMLElement, event);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The draggable (and keyboard-operable) divider between two Panels.
|
|
94
|
+
*
|
|
95
|
+
* Follows the WAI-ARIA window-splitter pattern, and controls the Panel
|
|
96
|
+
* immediately before it. Finds its group via DOM context, so it must be
|
|
97
|
+
* rendered inside a `<Resizable>`.
|
|
98
|
+
*
|
|
99
|
+
* Give each handle an accessible name (e.g. `aria-label="Resize sidebar"`).
|
|
100
|
+
*/
|
|
101
|
+
export const Handle: TOC<HandleSignature> = <template>
|
|
102
|
+
<Consume @key={{GroupState}} as |ctx|>
|
|
103
|
+
<div
|
|
104
|
+
class="ember-primitives__resizable__handle"
|
|
105
|
+
role="separator"
|
|
106
|
+
tabindex="0"
|
|
107
|
+
data-orientation={{ctx.data.orientation}}
|
|
108
|
+
{{on "pointerdown" (onPointerDown ctx.data)}}
|
|
109
|
+
{{on "keydown" (onKeyDown ctx.data)}}
|
|
110
|
+
...attributes
|
|
111
|
+
>
|
|
112
|
+
{{yield}}
|
|
113
|
+
</div>
|
|
114
|
+
</Consume>
|
|
115
|
+
</template>;
|
|
116
|
+
|
|
117
|
+
export interface Signature {
|
|
118
|
+
Element: HTMLDivElement;
|
|
119
|
+
Args: {
|
|
120
|
+
/**
|
|
121
|
+
* Which direction the panels are laid out in.
|
|
122
|
+
*
|
|
123
|
+
* `horizontal` (the default) places panels side-by-side (resizing along the x-axis),
|
|
124
|
+
* `vertical` stacks them (resizing along the y-axis).
|
|
125
|
+
*
|
|
126
|
+
* May be changed while rendered; panels keep their sizes.
|
|
127
|
+
*/
|
|
128
|
+
orientation?: Orientation;
|
|
129
|
+
/**
|
|
130
|
+
* Called with the panels' sizes (percentages, in document order)
|
|
131
|
+
* whenever the layout changes.
|
|
132
|
+
*
|
|
133
|
+
* Useful for persisting the layout.
|
|
134
|
+
*/
|
|
135
|
+
onLayoutChange?: (sizes: number[]) => void;
|
|
136
|
+
};
|
|
137
|
+
Blocks: {
|
|
138
|
+
default: [];
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* A group of resizable panels, separated by draggable handles.
|
|
144
|
+
*
|
|
145
|
+
* Render `<Panel>` and `<Handle>` components inside -- they are their
|
|
146
|
+
* own imports, and find the group via DOM context / DOM queries.
|
|
147
|
+
*
|
|
148
|
+
* Groups can be nested (a `<Resizable>` inside a Panel) to build
|
|
149
|
+
* tree-shaped tiling layouts, i3 / tmux style.
|
|
150
|
+
*/
|
|
151
|
+
export class Resizable extends Component<Signature> {
|
|
152
|
+
state = new GroupState({
|
|
153
|
+
orientation: () => this.args.orientation,
|
|
154
|
+
onLayoutChange: () => this.args.onLayoutChange,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
attach = modifier((element: HTMLElement) => this.state.attach(element));
|
|
158
|
+
|
|
159
|
+
<template>
|
|
160
|
+
<div
|
|
161
|
+
class="ember-primitives__resizable"
|
|
162
|
+
data-orientation={{this.state.orientation}}
|
|
163
|
+
{{this.attach}}
|
|
164
|
+
...attributes
|
|
165
|
+
>
|
|
166
|
+
<Provide @data={{this.state}} @key={{GroupState}}>
|
|
167
|
+
{{yield}}
|
|
168
|
+
</Provide>
|
|
169
|
+
</div>
|
|
170
|
+
</template>
|
|
171
|
+
}
|
package/src/dom-context.gts
CHANGED
|
@@ -41,13 +41,16 @@ export class Provide<Data extends object> extends Component<{
|
|
|
41
41
|
data: Data | (() => Data) | Newable<Data>;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Optionally, you may use
|
|
44
|
+
* Optionally, you may use keys to reference the data in the Provide,
|
|
45
|
+
* e.g. when `@data` is an already-created instance and consumers
|
|
46
|
+
* reference it by its class.
|
|
45
47
|
*
|
|
46
|
-
*
|
|
48
|
+
* Keys are compared by identity. String keys are not recommended,
|
|
49
|
+
* because when using a class or other object-like structure,
|
|
47
50
|
* the type in the `<Consume>` component can be derived from that class or object-like structure.
|
|
48
51
|
* With string keys, the `<Consume>` type will be unknown.
|
|
49
52
|
*/
|
|
50
|
-
key?: string;
|
|
53
|
+
key?: string | object;
|
|
51
54
|
|
|
52
55
|
/**
|
|
53
56
|
* Can be used to either customize the element tag ( defaults to div )
|
package/src/index.ts
CHANGED
|
@@ -36,6 +36,11 @@ export { PortalTargets } from './components/portal-targets.gts';
|
|
|
36
36
|
export { TARGETS as PORTALS } from './components/portal-targets.gts';
|
|
37
37
|
export { Progress } from './components/progress.gts';
|
|
38
38
|
export { Rating } from './components/rating.gts';
|
|
39
|
+
export {
|
|
40
|
+
Resizable,
|
|
41
|
+
Handle as ResizableHandle,
|
|
42
|
+
Panel as ResizablePanel,
|
|
43
|
+
} from './components/resizable.gts';
|
|
39
44
|
export { Scroller } from './components/scroller.gts';
|
|
40
45
|
export { Separator } from './components/separator.gts';
|
|
41
46
|
export { Shadowed } from './components/shadowed.gts';
|