@getaster/elements 0.0.0-stage → 0.1.0-preview.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/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +6 -2
- package/bin/aster-theme-check.js +317 -0
- package/dist/base/drag.d.ts +45 -0
- package/dist/base/drag.js +139 -0
- package/dist/base/element.d.ts +51 -0
- package/dist/base/element.js +133 -0
- package/dist/breadcrumbs/breadcrumbs.d.ts +23 -0
- package/dist/breadcrumbs/breadcrumbs.js +51 -0
- package/dist/button/button.d.ts +37 -0
- package/dist/button/button.js +108 -0
- package/dist/caret/caret-group.d.ts +14 -0
- package/dist/caret/caret-group.js +71 -0
- package/dist/carousel/carousel.d.ts +28 -0
- package/dist/carousel/carousel.js +134 -0
- package/dist/component/component.d.ts +73 -0
- package/dist/component/component.js +190 -0
- package/dist/component/echarts.d.ts +46 -0
- package/dist/component/echarts.js +95 -0
- package/dist/composition/authoring.d.ts +157 -0
- package/dist/composition/authoring.js +291 -0
- package/dist/composition/builtins.d.ts +1130 -0
- package/dist/composition/builtins.js +318 -0
- package/dist/composition/command-bar.d.ts +18 -0
- package/dist/composition/command-bar.js +34 -0
- package/dist/composition/commands.d.ts +14 -0
- package/dist/composition/commands.js +59 -0
- package/dist/composition/composite.d.ts +48 -0
- package/dist/composition/composite.js +409 -0
- package/dist/composition/contracts.d.ts +63 -0
- package/dist/composition/contracts.js +97 -0
- package/dist/composition/definition.d.ts +94 -0
- package/dist/composition/definition.js +291 -0
- package/dist/composition/element.d.ts +35 -0
- package/dist/composition/element.js +51 -0
- package/dist/composition/registry.d.ts +83 -0
- package/dist/composition/registry.js +99 -0
- package/dist/composition/schema.d.ts +9 -0
- package/dist/composition/schema.js +139 -0
- package/dist/composition/sessions.d.ts +15 -0
- package/dist/composition/sessions.js +61 -0
- package/dist/dashboard/dashboard.d.ts +26 -0
- package/dist/dashboard/dashboard.js +296 -0
- package/dist/dashboard/layout.d.ts +19 -0
- package/dist/dashboard/layout.js +48 -0
- package/dist/dashboard/widget.d.ts +42 -0
- package/dist/dashboard/widget.js +165 -0
- package/dist/date/calendar.d.ts +34 -0
- package/dist/date/calendar.js +137 -0
- package/dist/date/date-field.d.ts +18 -0
- package/dist/date/date-field.js +81 -0
- package/dist/date/dates.d.ts +22 -0
- package/dist/date/dates.js +80 -0
- package/dist/dialog/dialog.d.ts +23 -0
- package/dist/dialog/dialog.js +70 -0
- package/dist/field/bound-field.d.ts +55 -0
- package/dist/field/bound-field.js +139 -0
- package/dist/field/check.d.ts +11 -0
- package/dist/field/check.js +26 -0
- package/dist/field/composite-field.d.ts +35 -0
- package/dist/field/composite-field.js +88 -0
- package/dist/field/field.d.ts +29 -0
- package/dist/field/field.js +75 -0
- package/dist/field/input.d.ts +15 -0
- package/dist/field/input.js +18 -0
- package/dist/field/number-field.d.ts +33 -0
- package/dist/field/number-field.js +179 -0
- package/dist/field/numeric.d.ts +4 -0
- package/dist/field/numeric.js +57 -0
- package/dist/field/values.d.ts +14 -0
- package/dist/field/values.js +60 -0
- package/dist/filter/filter-builder.d.ts +18 -0
- package/dist/filter/filter-builder.js +305 -0
- package/dist/form/controls.d.ts +20 -0
- package/dist/form/controls.js +34 -0
- package/dist/form/form.d.ts +46 -0
- package/dist/form/form.js +85 -0
- package/dist/format.d.ts +10 -0
- package/dist/format.js +57 -0
- package/dist/grid/filters.d.ts +16 -0
- package/dist/grid/filters.js +66 -0
- package/dist/grid/grid.d.ts +209 -0
- package/dist/grid/grid.js +2587 -0
- package/dist/grid/rows.d.ts +32 -0
- package/dist/grid/rows.js +89 -0
- package/dist/grid/view.d.ts +69 -0
- package/dist/grid/view.js +172 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +61 -0
- package/dist/layout/stack.d.ts +112 -0
- package/dist/layout/stack.js +21 -0
- package/dist/list-edit/list-edit.d.ts +42 -0
- package/dist/list-edit/list-edit.js +220 -0
- package/dist/listbox/listbox.d.ts +45 -0
- package/dist/listbox/listbox.js +187 -0
- package/dist/menu/menu.d.ts +55 -0
- package/dist/menu/menu.js +286 -0
- package/dist/motion.d.ts +8 -0
- package/dist/motion.js +23 -0
- package/dist/overlay/anchor.d.ts +18 -0
- package/dist/overlay/anchor.js +41 -0
- package/dist/picker/options.d.ts +59 -0
- package/dist/picker/options.js +97 -0
- package/dist/picker/picker.d.ts +46 -0
- package/dist/picker/picker.js +492 -0
- package/dist/picker/tree-choices.d.ts +38 -0
- package/dist/picker/tree-choices.js +72 -0
- package/dist/picker/tree-picker.d.ts +29 -0
- package/dist/picker/tree-picker.js +282 -0
- package/dist/progress/policy.d.ts +5 -0
- package/dist/progress/policy.js +28 -0
- package/dist/progress/status.d.ts +20 -0
- package/dist/progress/status.js +38 -0
- package/dist/rule/operators.d.ts +8 -0
- package/dist/rule/operators.js +9 -0
- package/dist/rule/rule-editor.d.ts +57 -0
- package/dist/rule/rule-editor.js +290 -0
- package/dist/section/accordion.d.ts +24 -0
- package/dist/section/accordion.js +90 -0
- package/dist/section/section.d.ts +30 -0
- package/dist/section/section.js +99 -0
- package/dist/select/choice-element.d.ts +20 -0
- package/dist/select/choice-element.js +55 -0
- package/dist/select/choice.d.ts +34 -0
- package/dist/select/choice.js +122 -0
- package/dist/select/many.d.ts +13 -0
- package/dist/select/many.js +20 -0
- package/dist/select/select.d.ts +16 -0
- package/dist/select/select.js +40 -0
- package/dist/sidebar/sidebar.d.ts +47 -0
- package/dist/sidebar/sidebar.js +105 -0
- package/dist/slicer/slicer.d.ts +26 -0
- package/dist/slicer/slicer.js +140 -0
- package/dist/split/split.d.ts +41 -0
- package/dist/split/split.js +237 -0
- package/dist/styles/contract.d.ts +36 -0
- package/dist/styles/contract.js +39 -0
- package/dist/switch/switch.d.ts +22 -0
- package/dist/switch/switch.js +69 -0
- package/dist/tabs/tabs.d.ts +30 -0
- package/dist/tabs/tabs.js +202 -0
- package/dist/tile-grid/scroll.d.ts +9 -0
- package/dist/tile-grid/scroll.js +21 -0
- package/dist/tile-grid/tile-grid.d.ts +64 -0
- package/dist/tile-grid/tile-grid.js +734 -0
- package/dist/toast/toast.d.ts +25 -0
- package/dist/toast/toast.js +92 -0
- package/dist/tree/navigator.d.ts +41 -0
- package/dist/tree/navigator.js +228 -0
- package/dist/window/chrome.d.ts +3 -0
- package/dist/window/chrome.js +7 -0
- package/dist/window/window.d.ts +46 -0
- package/dist/window/window.js +347 -0
- package/dist/window/workspace.d.ts +29 -0
- package/dist/window/workspace.js +137 -0
- package/package.json +45 -4
- package/styles/aster-ui.css +1147 -0
- package/styles/base.css +88 -0
- package/styles/contract.ts +41 -0
- package/styles/elements.css +1058 -0
- package/styles/harbour.css +126 -0
- package/styles/lamplight.css +118 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { KeyText } from "@getaster/data";
|
|
2
|
+
/**
|
|
3
|
+
* Row offsets for a virtualized list whose rows have different heights.
|
|
4
|
+
* Heights are measured by key, so a measured row keeps its height when
|
|
5
|
+
* rows move; rows not measured yet (or not loaded) count as `estimate`.
|
|
6
|
+
*
|
|
7
|
+
* Offsets are prefix sums, rebuilt lazily after a change: O(rows) once per
|
|
8
|
+
* change, O(log rows) per lookup.
|
|
9
|
+
*/
|
|
10
|
+
export declare class RowHeights {
|
|
11
|
+
#private;
|
|
12
|
+
estimate: number;
|
|
13
|
+
constructor(estimate: number);
|
|
14
|
+
/** The rows, in order; `undefined` where a row isn't loaded. */
|
|
15
|
+
setKeys(keys: readonly (KeyText | undefined)[]): void;
|
|
16
|
+
get count(): number;
|
|
17
|
+
/** Whether a row's height has been measured. */
|
|
18
|
+
has(key: KeyText): boolean;
|
|
19
|
+
/** Records a row's height; returns whether it changed. */
|
|
20
|
+
measure(key: KeyText, height: number): boolean;
|
|
21
|
+
height(index: number): number;
|
|
22
|
+
/** The top of row `index`; `offset(count)` is the total height. */
|
|
23
|
+
offset(index: number): number;
|
|
24
|
+
total(): number;
|
|
25
|
+
/** The row at `y`: the last row whose top is at or above it. */
|
|
26
|
+
indexAt(y: number): number;
|
|
27
|
+
/** The rows to render for a viewport, with `overscan` pixels either side. */
|
|
28
|
+
window(top: number, height: number, overscan: number): {
|
|
29
|
+
start: number;
|
|
30
|
+
end: number;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row offsets for a virtualized list whose rows have different heights.
|
|
3
|
+
* Heights are measured by key, so a measured row keeps its height when
|
|
4
|
+
* rows move; rows not measured yet (or not loaded) count as `estimate`.
|
|
5
|
+
*
|
|
6
|
+
* Offsets are prefix sums, rebuilt lazily after a change: O(rows) once per
|
|
7
|
+
* change, O(log rows) per lookup.
|
|
8
|
+
*/
|
|
9
|
+
export class RowHeights {
|
|
10
|
+
estimate;
|
|
11
|
+
#measured = new Map();
|
|
12
|
+
#keys = [];
|
|
13
|
+
#prefix = new Float64Array(1);
|
|
14
|
+
#dirty = true;
|
|
15
|
+
constructor(estimate) {
|
|
16
|
+
this.estimate = estimate;
|
|
17
|
+
}
|
|
18
|
+
/** The rows, in order; `undefined` where a row isn't loaded. */
|
|
19
|
+
setKeys(keys) {
|
|
20
|
+
this.#keys = keys;
|
|
21
|
+
this.#dirty = true;
|
|
22
|
+
}
|
|
23
|
+
get count() {
|
|
24
|
+
return this.#keys.length;
|
|
25
|
+
}
|
|
26
|
+
/** Whether a row's height has been measured. */
|
|
27
|
+
has(key) {
|
|
28
|
+
return this.#measured.has(key);
|
|
29
|
+
}
|
|
30
|
+
/** Records a row's height; returns whether it changed. */
|
|
31
|
+
measure(key, height) {
|
|
32
|
+
if (this.#measured.get(key) === height)
|
|
33
|
+
return false;
|
|
34
|
+
this.#measured.set(key, height);
|
|
35
|
+
this.#dirty = true;
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
height(index) {
|
|
39
|
+
const key = this.#keys[index];
|
|
40
|
+
return (key !== undefined ? this.#measured.get(key) : undefined) ?? this.estimate;
|
|
41
|
+
}
|
|
42
|
+
/** The top of row `index`; `offset(count)` is the total height. */
|
|
43
|
+
offset(index) {
|
|
44
|
+
this.#build();
|
|
45
|
+
return this.#prefix[Math.max(0, Math.min(index, this.#keys.length))];
|
|
46
|
+
}
|
|
47
|
+
total() {
|
|
48
|
+
return this.offset(this.#keys.length);
|
|
49
|
+
}
|
|
50
|
+
/** The row at `y`: the last row whose top is at or above it. */
|
|
51
|
+
indexAt(y) {
|
|
52
|
+
this.#build();
|
|
53
|
+
const n = this.#keys.length;
|
|
54
|
+
if (n === 0)
|
|
55
|
+
return 0;
|
|
56
|
+
let lo = 0;
|
|
57
|
+
let hi = n - 1;
|
|
58
|
+
while (lo < hi) {
|
|
59
|
+
const mid = (lo + hi + 1) >> 1;
|
|
60
|
+
if (this.#prefix[mid] <= y)
|
|
61
|
+
lo = mid;
|
|
62
|
+
else
|
|
63
|
+
hi = mid - 1;
|
|
64
|
+
}
|
|
65
|
+
return lo;
|
|
66
|
+
}
|
|
67
|
+
/** The rows to render for a viewport, with `overscan` pixels either side. */
|
|
68
|
+
window(top, height, overscan) {
|
|
69
|
+
if (this.#keys.length === 0)
|
|
70
|
+
return { start: 0, end: 0 };
|
|
71
|
+
const start = this.indexAt(Math.max(0, top - overscan));
|
|
72
|
+
const end = Math.min(this.#keys.length, this.indexAt(top + height + overscan) + 1);
|
|
73
|
+
return { start, end };
|
|
74
|
+
}
|
|
75
|
+
#build() {
|
|
76
|
+
if (!this.#dirty)
|
|
77
|
+
return;
|
|
78
|
+
const n = this.#keys.length;
|
|
79
|
+
if (this.#prefix.length !== n + 1)
|
|
80
|
+
this.#prefix = new Float64Array(n + 1);
|
|
81
|
+
let sum = 0;
|
|
82
|
+
for (let i = 0; i < n; i++) {
|
|
83
|
+
this.#prefix[i] = sum;
|
|
84
|
+
sum += this.height(i);
|
|
85
|
+
}
|
|
86
|
+
this.#prefix[n] = sum;
|
|
87
|
+
this.#dirty = false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Criteria, EntityType, Field, Query, SortKey } from "@getaster/data";
|
|
2
|
+
export interface GridColumn {
|
|
3
|
+
readonly field: string;
|
|
4
|
+
/** Pixels; a column without a width shares the space left over. */
|
|
5
|
+
readonly width?: number;
|
|
6
|
+
readonly hidden?: boolean;
|
|
7
|
+
/** Server field or navigation path used for ordering; display and filtering retain `field`. */
|
|
8
|
+
readonly sortField?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Everything a person can shape about a grid, as data: it's saved, restored,
|
|
12
|
+
* published to the page scope, and the collection's query follows it.
|
|
13
|
+
*/
|
|
14
|
+
export interface GridView {
|
|
15
|
+
/** In display order. */
|
|
16
|
+
readonly columns: readonly GridColumn[];
|
|
17
|
+
readonly sort: readonly SortKey[];
|
|
18
|
+
/** Criteria by column; all of them hold. */
|
|
19
|
+
readonly filters: Readonly<Record<string, Criteria>>;
|
|
20
|
+
/** An advanced expression, ANDed with column filters and the host's base. */
|
|
21
|
+
readonly criteria?: Criteria;
|
|
22
|
+
/** One field, or fields in outermost-to-innermost order. */
|
|
23
|
+
readonly groupBy?: string | readonly string[];
|
|
24
|
+
/** How many leading visible columns stay in place when scrolling sideways. */
|
|
25
|
+
readonly frozen: number;
|
|
26
|
+
}
|
|
27
|
+
/** The query a view describes, within `base` (such as "this project only"). */
|
|
28
|
+
/** `sortPaths` maps a column to what it sorts by, for a lookup column the related record's display field. */
|
|
29
|
+
export declare function viewQuery(set: string, view: GridView, base?: Criteria, sortPaths?: Readonly<Record<string, string>>): Query;
|
|
30
|
+
/** Every field of `type` that has a value to show, in declaration order, the key last. */
|
|
31
|
+
export declare function defaultView(type: EntityType): GridView;
|
|
32
|
+
/** The column's track: its width, or a share of the space with a floor that suits its type. */
|
|
33
|
+
export declare function track(column: GridColumn, field: Field | undefined): string;
|
|
34
|
+
export declare function naturalWidth(field: Field | undefined): number;
|
|
35
|
+
/** Numbers line up on their right edge. */
|
|
36
|
+
export declare function isNumeric(field: Field | undefined): boolean;
|
|
37
|
+
/** The view with one sort key set: alone, or added to the others when `add`. */
|
|
38
|
+
export declare function sortBy(view: GridView, field: string, add: boolean): GridView;
|
|
39
|
+
export declare function removeSort(view: GridView, field: string): GridView;
|
|
40
|
+
/** Sets one direction for a column, alone or added to the sort. */
|
|
41
|
+
export declare function sortDirection(view: GridView, field: string, descending: boolean, add: boolean): GridView;
|
|
42
|
+
export declare function setHidden(view: GridView, field: string, hidden: boolean): GridView;
|
|
43
|
+
/** Moves a column to `to`, an index among all columns (hidden ones included). */
|
|
44
|
+
export declare function moveColumn(view: GridView, field: string, to: number): GridView;
|
|
45
|
+
/** Moves a column one place among the visible columns. */
|
|
46
|
+
export declare function nudgeColumn(view: GridView, field: string, step: -1 | 1): GridView;
|
|
47
|
+
export declare function setWidth(view: GridView, field: string, width: number | undefined): GridView;
|
|
48
|
+
/**
|
|
49
|
+
* Freezes the visible columns up to and including `field`. Frozen columns
|
|
50
|
+
* need fixed widths, so any without one take `fallback(field)`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function freezeThrough(view: GridView, field: string, fallback: (field: string) => number): GridView;
|
|
53
|
+
export declare function setFilter(view: GridView, field: string, criteria: Criteria | undefined): GridView;
|
|
54
|
+
export declare function groupFields(view: GridView | undefined): readonly string[];
|
|
55
|
+
export declare function setGroup(view: GridView, field: string | readonly string[] | undefined): GridView;
|
|
56
|
+
/** A person's views for one grid: the one in use, and any saved by name. */
|
|
57
|
+
export interface SavedViews {
|
|
58
|
+
readonly current?: GridView;
|
|
59
|
+
readonly named: Readonly<Record<string, GridView>>;
|
|
60
|
+
}
|
|
61
|
+
/** Read from this browser; empty when storage is unavailable or holds something else. */
|
|
62
|
+
export declare function loadViews(key: string): SavedViews;
|
|
63
|
+
export declare function storeViews(key: string, views: SavedViews): void;
|
|
64
|
+
/**
|
|
65
|
+
* A stored view against the columns the grid offers now: unknown columns
|
|
66
|
+
* drop out and new ones join at the end, hidden, so a change to the page
|
|
67
|
+
* never breaks a saved view.
|
|
68
|
+
*/
|
|
69
|
+
export declare function reconcile(stored: GridView, offered: GridView): GridView;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/** The query a view describes, within `base` (such as "this project only"). */
|
|
2
|
+
/** `sortPaths` maps a column to what it sorts by, for a lookup column the related record's display field. */
|
|
3
|
+
export function viewQuery(set, view, base, sortPaths = {}) {
|
|
4
|
+
const parts = [...(base ? [base] : []), ...Object.values(view.filters), ...(view.criteria ? [view.criteria] : [])];
|
|
5
|
+
const filter = parts.length === 0 ? undefined : parts.length === 1 ? parts[0] : { op: "and", args: parts };
|
|
6
|
+
const paths = { ...sortPaths, ...Object.fromEntries(view.columns.filter(c => c.sortField).map(c => [c.field, c.sortField])) };
|
|
7
|
+
const orderBy = view.sort.map((k) => (paths[k.field] ? { ...k, field: paths[k.field] } : k));
|
|
8
|
+
return { set, ...(filter ? { filter } : {}), ...(orderBy.length ? { orderBy } : {}) };
|
|
9
|
+
}
|
|
10
|
+
/** Every field of `type` that has a value to show, in declaration order, the key last. */
|
|
11
|
+
export function defaultView(type) {
|
|
12
|
+
const fields = type.fields.filter((f) => !type.key.includes(f.name)).map((f) => ({ field: f.name }));
|
|
13
|
+
return { columns: fields, sort: [], filters: {}, frozen: 0 };
|
|
14
|
+
}
|
|
15
|
+
/** The column's track: its width, or a share of the space with a floor that suits its type. */
|
|
16
|
+
export function track(column, field) {
|
|
17
|
+
if (column.width !== undefined)
|
|
18
|
+
return `${column.width}px`;
|
|
19
|
+
const prose = field?.type === "Edm.String" && !field.allowedValues && (field.maxLength ?? 0) > 500;
|
|
20
|
+
return prose ? "minmax(260px, 3fr)" : `minmax(${naturalWidth(field)}px, 1fr)`;
|
|
21
|
+
}
|
|
22
|
+
export function naturalWidth(field) {
|
|
23
|
+
switch (field?.type) {
|
|
24
|
+
case "Edm.Boolean":
|
|
25
|
+
return 80;
|
|
26
|
+
case "Edm.Date":
|
|
27
|
+
return 110;
|
|
28
|
+
case "Edm.DateTimeOffset":
|
|
29
|
+
return 150;
|
|
30
|
+
case "Edm.Byte":
|
|
31
|
+
case "Edm.SByte":
|
|
32
|
+
case "Edm.Int16":
|
|
33
|
+
case "Edm.Int32":
|
|
34
|
+
case "Edm.Int64":
|
|
35
|
+
case "Edm.Decimal":
|
|
36
|
+
case "Edm.Double":
|
|
37
|
+
case "Edm.Single":
|
|
38
|
+
return 90;
|
|
39
|
+
default:
|
|
40
|
+
return field?.allowedValues ? 110 : 160;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Numbers line up on their right edge. */
|
|
44
|
+
export function isNumeric(field) {
|
|
45
|
+
return naturalWidth(field) === 90;
|
|
46
|
+
}
|
|
47
|
+
/** The view with one sort key set: alone, or added to the others when `add`. */
|
|
48
|
+
export function sortBy(view, field, add) {
|
|
49
|
+
const current = view.sort.find((s) => s.field === field);
|
|
50
|
+
const next = { field, ...(current && !current.descending ? { descending: true } : {}) };
|
|
51
|
+
const rest = add ? view.sort.filter((s) => s.field !== field) : [];
|
|
52
|
+
return { ...view, sort: current && add ? view.sort.map((s) => (s.field === field ? next : s)) : [...rest, next] };
|
|
53
|
+
}
|
|
54
|
+
export function removeSort(view, field) {
|
|
55
|
+
return { ...view, sort: view.sort.filter((s) => s.field !== field) };
|
|
56
|
+
}
|
|
57
|
+
/** Sets one direction for a column, alone or added to the sort. */
|
|
58
|
+
export function sortDirection(view, field, descending, add) {
|
|
59
|
+
const key = { field, ...(descending ? { descending } : {}) };
|
|
60
|
+
if (!add)
|
|
61
|
+
return { ...view, sort: [key] };
|
|
62
|
+
const at = view.sort.findIndex((s) => s.field === field);
|
|
63
|
+
return { ...view, sort: at >= 0 ? view.sort.map((s, i) => (i === at ? key : s)) : [...view.sort, key] };
|
|
64
|
+
}
|
|
65
|
+
export function setHidden(view, field, hidden) {
|
|
66
|
+
const columns = view.columns.map((c) => (c.field === field ? { ...c, hidden } : c));
|
|
67
|
+
const visible = columns.filter((c) => !c.hidden);
|
|
68
|
+
return { ...view, columns, frozen: Math.min(view.frozen, Math.max(0, visible.length - 1)) };
|
|
69
|
+
}
|
|
70
|
+
/** Moves a column to `to`, an index among all columns (hidden ones included). */
|
|
71
|
+
export function moveColumn(view, field, to) {
|
|
72
|
+
const from = view.columns.findIndex((c) => c.field === field);
|
|
73
|
+
if (from < 0)
|
|
74
|
+
return view;
|
|
75
|
+
const columns = [...view.columns];
|
|
76
|
+
const [column] = columns.splice(from, 1);
|
|
77
|
+
columns.splice(Math.max(0, Math.min(columns.length, to)), 0, column);
|
|
78
|
+
return { ...view, columns };
|
|
79
|
+
}
|
|
80
|
+
/** Moves a column one place among the visible columns. */
|
|
81
|
+
export function nudgeColumn(view, field, step) {
|
|
82
|
+
const visible = view.columns.filter((c) => !c.hidden);
|
|
83
|
+
const at = visible.findIndex((c) => c.field === field);
|
|
84
|
+
const neighbour = visible[at + step];
|
|
85
|
+
if (at < 0 || !neighbour)
|
|
86
|
+
return view;
|
|
87
|
+
return moveColumn(view, field, view.columns.findIndex((c) => c.field === neighbour.field));
|
|
88
|
+
}
|
|
89
|
+
export function setWidth(view, field, width) {
|
|
90
|
+
return {
|
|
91
|
+
...view,
|
|
92
|
+
columns: view.columns.map((c) => {
|
|
93
|
+
if (c.field !== field)
|
|
94
|
+
return c;
|
|
95
|
+
const { width: _, ...rest } = c;
|
|
96
|
+
return width === undefined ? rest : { ...rest, width: Math.round(Math.max(48, width)) };
|
|
97
|
+
}),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Freezes the visible columns up to and including `field`. Frozen columns
|
|
102
|
+
* need fixed widths, so any without one take `fallback(field)`.
|
|
103
|
+
*/
|
|
104
|
+
export function freezeThrough(view, field, fallback) {
|
|
105
|
+
const visible = view.columns.filter((c) => !c.hidden);
|
|
106
|
+
const at = visible.findIndex((c) => c.field === field);
|
|
107
|
+
if (at < 0)
|
|
108
|
+
return view;
|
|
109
|
+
const fixed = new Set(visible.slice(0, at + 1).map((c) => c.field));
|
|
110
|
+
return {
|
|
111
|
+
...view,
|
|
112
|
+
frozen: at + 1,
|
|
113
|
+
columns: view.columns.map((c) => (fixed.has(c.field) && c.width === undefined ? { ...c, width: fallback(c.field) } : c)),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export function setFilter(view, field, criteria) {
|
|
117
|
+
const { [field]: _, ...rest } = view.filters;
|
|
118
|
+
return { ...view, filters: criteria ? { ...rest, [field]: criteria } : rest };
|
|
119
|
+
}
|
|
120
|
+
export function groupFields(view) {
|
|
121
|
+
const value = view?.groupBy;
|
|
122
|
+
if (value === undefined)
|
|
123
|
+
return [];
|
|
124
|
+
const fields = typeof value === "string" ? [value] : value;
|
|
125
|
+
if (!Array.isArray(fields) || fields.some((f) => typeof f !== "string" || !f) || new Set(fields).size !== fields.length)
|
|
126
|
+
throw new Error("Grouping needs distinct nonempty fields");
|
|
127
|
+
return fields;
|
|
128
|
+
}
|
|
129
|
+
export function setGroup(view, field) {
|
|
130
|
+
const { groupBy: _, ...rest } = view;
|
|
131
|
+
const fields = groupFields({ ...rest, ...(field === undefined ? {} : { groupBy: field }) });
|
|
132
|
+
if (!fields.length)
|
|
133
|
+
return rest;
|
|
134
|
+
return { ...rest, groupBy: fields.length === 1 ? fields[0] : [...fields] };
|
|
135
|
+
}
|
|
136
|
+
/** Read from this browser; empty when storage is unavailable or holds something else. */
|
|
137
|
+
export function loadViews(key) {
|
|
138
|
+
try {
|
|
139
|
+
const raw = localStorage.getItem(`aster-grid:${key}`);
|
|
140
|
+
const parsed = raw ? JSON.parse(raw) : undefined;
|
|
141
|
+
return parsed && typeof parsed.named === "object" ? parsed : { named: {} };
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return { named: {} };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export function storeViews(key, views) {
|
|
148
|
+
try {
|
|
149
|
+
localStorage.setItem(`aster-grid:${key}`, JSON.stringify(views));
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Not kept; the view still applies until the page closes.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A stored view against the columns the grid offers now: unknown columns
|
|
157
|
+
* drop out and new ones join at the end, hidden, so a change to the page
|
|
158
|
+
* never breaks a saved view.
|
|
159
|
+
*/
|
|
160
|
+
export function reconcile(stored, offered) {
|
|
161
|
+
const known = new Set(offered.columns.map((c) => c.field));
|
|
162
|
+
const kept = stored.columns.filter((c) => known.has(c.field)).map(({ sortField: _, ...column }) => {
|
|
163
|
+
const sortField = offered.columns.find(c => c.field === column.field)?.sortField;
|
|
164
|
+
return sortField ? { ...column, sortField } : column;
|
|
165
|
+
});
|
|
166
|
+
const have = new Set(kept.map((c) => c.field));
|
|
167
|
+
const added = offered.columns.filter((c) => !have.has(c.field)).map((c) => ({ ...c, hidden: true }));
|
|
168
|
+
const filters = Object.fromEntries(Object.entries(stored.filters).filter(([f]) => known.has(f)));
|
|
169
|
+
const sort = stored.sort.filter((s) => known.has(s.field));
|
|
170
|
+
const view = { ...stored, columns: [...kept, ...added], filters, sort };
|
|
171
|
+
return setGroup(view, groupFields(view).filter((field) => known.has(field)));
|
|
172
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export { ProgressStatus } from "./progress/status.ts";
|
|
2
|
+
export { provideProgressPolicy, progressPolicyOf } from "./progress/policy.ts";
|
|
3
|
+
export { asterComponents } from "./composition/builtins.ts";
|
|
4
|
+
export { Sidebar, sidebarItems, type SidebarItem } from "./sidebar/sidebar.ts";
|
|
5
|
+
export { AsterElement, define, each, provideScope, read, scopeOf, type Bindable, type View } from "./base/element.ts";
|
|
6
|
+
export { Composite, compositeComponent, type CompositeOptions, type CompositeChildHandle, type CompositePlacement } from "./composition/composite.ts";
|
|
7
|
+
export { CommandBar } from "./composition/command-bar.ts";
|
|
8
|
+
export { defineCompositeRegistry, defineCompositeRenderer, CompositeAuthoring, type RegistryCatalog, type CompositeDiagnostic, type CompositeCompletion } from "./composition/authoring.ts";
|
|
9
|
+
export { defineElement, elementProperty, type ElementProperty, type ElementProperties, type ElementValues, type DeclaredElement } from "./composition/element.ts";
|
|
10
|
+
export { defineComposite, deriveComposite, CompositeError, located, type CompositeDefinition, type CompositeChild, type CompositeLayout, type CompositeValue, type CompositeSources, type CompositeLocation, type CompositeCustomization, type CompositeChildCustomization, type CompositeOverrides, type CompositeVariant } from "./composition/definition.ts";
|
|
11
|
+
export { CompositeRegistry, compositeElement, type CompositeResolver, type CompositeValues, type CompositeContract, type CompositeProperty, type CompositeModel, type CompositeModelType, type CompositeMount, type CompositeSession, type CompositeFactory, type CompositeComponentType, type CompositeRenderer } from "./composition/registry.ts";
|
|
12
|
+
export { compositeTypes, defineCompositeModel, describeCompositeContract, type CompositeType, type CompositeTypes, type CompositeContractValues, type TypedCompositeModel } from "./composition/contracts.ts";
|
|
13
|
+
export { CaretGroup } from "./caret/caret-group.ts";
|
|
14
|
+
export { Tabs, type TabItem } from "./tabs/tabs.ts";
|
|
15
|
+
export { TileGrid, type TileContent, type TileState, type TileRenderer, type TilePresenter, type TileOpenDetail } from "./tile-grid/tile-grid.ts";
|
|
16
|
+
export { Listbox, type RowMenuDetail, type RowRenderer } from "./listbox/listbox.ts";
|
|
17
|
+
export { Button } from "./button/button.ts";
|
|
18
|
+
export { Field } from "./field/field.ts";
|
|
19
|
+
export { Switch, type SwitchBinding } from "./switch/switch.ts";
|
|
20
|
+
export { Dialog } from "./dialog/dialog.ts";
|
|
21
|
+
export { Window, type WindowState, type WindowBounds, type WindowPlacement } from "./window/window.ts";
|
|
22
|
+
export { Workspace, type WorkspaceEntry, type WorkspaceSnapshot } from "./window/workspace.ts";
|
|
23
|
+
export { Dashboard } from "./dashboard/dashboard.ts";
|
|
24
|
+
export type { DashboardValue, DashboardConfig, DashboardSize, DashboardWidget, DashboardSnapshot } from "./dashboard/layout.ts";
|
|
25
|
+
export type { DashboardMount, DashboardSession, DashboardWidgetType } from "./dashboard/widget.ts";
|
|
26
|
+
export { Toaster, announce, type ToastAction } from "./toast/toast.ts";
|
|
27
|
+
export { Menu, type MenuItem } from "./menu/menu.ts";
|
|
28
|
+
export { morph, setScheme } from "./motion.ts";
|
|
29
|
+
export { absoluteTime, compactMoney, relativeTime } from "./format.ts";
|
|
30
|
+
export { BoundField, type ControlContext } from "./field/bound-field.ts";
|
|
31
|
+
export { CompositeField, type CompositeFieldContext } from "./field/composite-field.ts";
|
|
32
|
+
export { NumberField, type NumericType, type NumericValue } from "./field/number-field.ts";
|
|
33
|
+
export { Stack, HorizontalLayout, VerticalLayout } from "./layout/stack.ts";
|
|
34
|
+
export { Breadcrumbs, type BreadcrumbItem } from "./breadcrumbs/breadcrumbs.ts";
|
|
35
|
+
export { Accordion, type AccordionItem } from "./section/accordion.ts";
|
|
36
|
+
export { Check } from "./field/check.ts";
|
|
37
|
+
export { formatValue, parseInput } from "./field/values.ts";
|
|
38
|
+
export { Select } from "./select/select.ts";
|
|
39
|
+
export { Choice } from "./select/choice-element.ts";
|
|
40
|
+
export { ChoiceState, choiceView, type ChoiceProps, type Option } from "./select/choice.ts";
|
|
41
|
+
export { Picker } from "./picker/picker.ts";
|
|
42
|
+
export { PickerOptions, type OptionsSpec } from "./picker/options.ts";
|
|
43
|
+
export { TreePicker } from "./picker/tree-picker.ts";
|
|
44
|
+
export { TreeChoices, type TreeChoicesSpec } from "./picker/tree-choices.ts";
|
|
45
|
+
export { DateField } from "./date/date-field.ts";
|
|
46
|
+
export { formatDate, parseDate, setClock } from "./date/dates.ts";
|
|
47
|
+
export { Section } from "./section/section.ts";
|
|
48
|
+
export { Form, type FormField, type FormItem, type FormSection, type FormValue } from "./form/form.ts";
|
|
49
|
+
export { controlFor } from "./form/controls.ts";
|
|
50
|
+
export { Split } from "./split/split.ts";
|
|
51
|
+
export { ListEditor, type ListColumn } from "./list-edit/list-edit.ts";
|
|
52
|
+
export { Grid, type CellRenderer, type CellFormatter, type GridSummary, type GridCsvOptions, type Expansion, type ExpansionEditor, type GridTree, type Lookup, type RowControl, type RowState } from "./grid/grid.ts";
|
|
53
|
+
export { RowHeights } from "./grid/rows.ts";
|
|
54
|
+
export { TreeNavigator } from "./tree/navigator.ts";
|
|
55
|
+
export { Carousel, type Slide } from "./carousel/carousel.ts";
|
|
56
|
+
export { RuleEditor, type RuleField } from "./rule/rule-editor.ts";
|
|
57
|
+
export { FilterBuilder } from "./filter/filter-builder.ts";
|
|
58
|
+
export { ComponentHost, type ComponentAdapter, type ComponentSession, type ComponentMount, type ComponentEnvironment } from "./component/component.ts";
|
|
59
|
+
export { echartsAdapter, echartsColors, type EChartsAdapterOptions, type EChartsRuntime, type EChartsInstance } from "./component/echarts.ts";
|
|
60
|
+
export { Slicer } from "./slicer/slicer.ts";
|
|
61
|
+
export { defaultView, sortBy, viewQuery, type GridColumn, type GridView } from "./grid/view.ts";
|
|
62
|
+
export { DENSITIES, DENSITY, DENSITY_NAMES, TOKENS, TOKEN_NAMES } from "./styles/contract.ts";
|
|
63
|
+
export { CompositeSessions, type CompositeSessionsOptions, type CompositeKeyedSession } from "./composition/sessions.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export { ProgressStatus } from "./progress/status.js";
|
|
2
|
+
export { provideProgressPolicy, progressPolicyOf } from "./progress/policy.js";
|
|
3
|
+
export { asterComponents } from "./composition/builtins.js";
|
|
4
|
+
export { Sidebar, sidebarItems } from "./sidebar/sidebar.js";
|
|
5
|
+
export { AsterElement, define, each, provideScope, read, scopeOf } from "./base/element.js";
|
|
6
|
+
export { Composite, compositeComponent } from "./composition/composite.js";
|
|
7
|
+
export { CommandBar } from "./composition/command-bar.js";
|
|
8
|
+
export { defineCompositeRegistry, defineCompositeRenderer, CompositeAuthoring } from "./composition/authoring.js";
|
|
9
|
+
export { defineElement, elementProperty } from "./composition/element.js";
|
|
10
|
+
export { defineComposite, deriveComposite, CompositeError, located } from "./composition/definition.js";
|
|
11
|
+
export { CompositeRegistry, compositeElement } from "./composition/registry.js";
|
|
12
|
+
export { compositeTypes, defineCompositeModel, describeCompositeContract } from "./composition/contracts.js";
|
|
13
|
+
export { CaretGroup } from "./caret/caret-group.js";
|
|
14
|
+
export { Tabs } from "./tabs/tabs.js";
|
|
15
|
+
export { TileGrid } from "./tile-grid/tile-grid.js";
|
|
16
|
+
export { Listbox } from "./listbox/listbox.js";
|
|
17
|
+
export { Button } from "./button/button.js";
|
|
18
|
+
export { Field } from "./field/field.js";
|
|
19
|
+
export { Switch } from "./switch/switch.js";
|
|
20
|
+
export { Dialog } from "./dialog/dialog.js";
|
|
21
|
+
export { Window } from "./window/window.js";
|
|
22
|
+
export { Workspace } from "./window/workspace.js";
|
|
23
|
+
export { Dashboard } from "./dashboard/dashboard.js";
|
|
24
|
+
export { Toaster, announce } from "./toast/toast.js";
|
|
25
|
+
export { Menu } from "./menu/menu.js";
|
|
26
|
+
export { morph, setScheme } from "./motion.js";
|
|
27
|
+
export { absoluteTime, compactMoney, relativeTime } from "./format.js";
|
|
28
|
+
export { BoundField } from "./field/bound-field.js";
|
|
29
|
+
export { CompositeField } from "./field/composite-field.js";
|
|
30
|
+
export { NumberField } from "./field/number-field.js";
|
|
31
|
+
export { Stack, HorizontalLayout, VerticalLayout } from "./layout/stack.js";
|
|
32
|
+
export { Breadcrumbs } from "./breadcrumbs/breadcrumbs.js";
|
|
33
|
+
export { Accordion } from "./section/accordion.js";
|
|
34
|
+
export { Check } from "./field/check.js";
|
|
35
|
+
export { formatValue, parseInput } from "./field/values.js";
|
|
36
|
+
export { Select } from "./select/select.js";
|
|
37
|
+
export { Choice } from "./select/choice-element.js";
|
|
38
|
+
export { ChoiceState, choiceView } from "./select/choice.js";
|
|
39
|
+
export { Picker } from "./picker/picker.js";
|
|
40
|
+
export { PickerOptions } from "./picker/options.js";
|
|
41
|
+
export { TreePicker } from "./picker/tree-picker.js";
|
|
42
|
+
export { TreeChoices } from "./picker/tree-choices.js";
|
|
43
|
+
export { DateField } from "./date/date-field.js";
|
|
44
|
+
export { formatDate, parseDate, setClock } from "./date/dates.js";
|
|
45
|
+
export { Section } from "./section/section.js";
|
|
46
|
+
export { Form } from "./form/form.js";
|
|
47
|
+
export { controlFor } from "./form/controls.js";
|
|
48
|
+
export { Split } from "./split/split.js";
|
|
49
|
+
export { ListEditor } from "./list-edit/list-edit.js";
|
|
50
|
+
export { Grid } from "./grid/grid.js";
|
|
51
|
+
export { RowHeights } from "./grid/rows.js";
|
|
52
|
+
export { TreeNavigator } from "./tree/navigator.js";
|
|
53
|
+
export { Carousel } from "./carousel/carousel.js";
|
|
54
|
+
export { RuleEditor } from "./rule/rule-editor.js";
|
|
55
|
+
export { FilterBuilder } from "./filter/filter-builder.js";
|
|
56
|
+
export { ComponentHost } from "./component/component.js";
|
|
57
|
+
export { echartsAdapter, echartsColors } from "./component/echarts.js";
|
|
58
|
+
export { Slicer } from "./slicer/slicer.js";
|
|
59
|
+
export { defaultView, sortBy, viewQuery } from "./grid/view.js";
|
|
60
|
+
export { DENSITIES, DENSITY, DENSITY_NAMES, TOKENS, TOKEN_NAMES } from "./styles/contract.js";
|
|
61
|
+
export { CompositeSessions } from "./composition/sessions.js";
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { View } from "../base/element.ts";
|
|
2
|
+
export declare const Stack: import("../index.ts").DeclaredElement<{
|
|
3
|
+
readonly direction: {
|
|
4
|
+
readonly type: import("../index.ts").CompositeType<"horizontal" | "vertical">;
|
|
5
|
+
readonly initial: () => "horizontal" | "vertical";
|
|
6
|
+
readonly description: string;
|
|
7
|
+
};
|
|
8
|
+
readonly gap: {
|
|
9
|
+
readonly type: import("../index.ts").CompositeType<"small" | "none" | "medium" | "large">;
|
|
10
|
+
readonly initial: () => "small" | "none" | "medium" | "large";
|
|
11
|
+
readonly description: string;
|
|
12
|
+
};
|
|
13
|
+
readonly align: {
|
|
14
|
+
readonly type: import("../index.ts").CompositeType<"center" | "stretch" | "start" | "end" | "baseline">;
|
|
15
|
+
readonly initial: () => "center" | "stretch" | "start" | "end" | "baseline";
|
|
16
|
+
readonly description: string;
|
|
17
|
+
};
|
|
18
|
+
readonly justify: {
|
|
19
|
+
readonly type: import("../index.ts").CompositeType<"center" | "start" | "end" | "space-between" | "space-around">;
|
|
20
|
+
readonly initial: () => "center" | "start" | "end" | "space-between" | "space-around";
|
|
21
|
+
readonly description: string;
|
|
22
|
+
};
|
|
23
|
+
readonly wrap: {
|
|
24
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
25
|
+
readonly initial: () => boolean;
|
|
26
|
+
readonly description: string;
|
|
27
|
+
};
|
|
28
|
+
readonly responsive: {
|
|
29
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
30
|
+
readonly initial: () => boolean;
|
|
31
|
+
readonly description: string;
|
|
32
|
+
};
|
|
33
|
+
readonly content: {
|
|
34
|
+
readonly type: import("../index.ts").CompositeType<View>;
|
|
35
|
+
readonly initial: () => View;
|
|
36
|
+
readonly description: string;
|
|
37
|
+
};
|
|
38
|
+
}>;
|
|
39
|
+
export declare const HorizontalLayout: import("../index.ts").DeclaredElement<{
|
|
40
|
+
readonly direction: {
|
|
41
|
+
readonly type: import("../index.ts").CompositeType<"horizontal" | "vertical">;
|
|
42
|
+
readonly initial: () => "horizontal" | "vertical";
|
|
43
|
+
readonly description: string;
|
|
44
|
+
};
|
|
45
|
+
readonly gap: {
|
|
46
|
+
readonly type: import("../index.ts").CompositeType<"small" | "none" | "medium" | "large">;
|
|
47
|
+
readonly initial: () => "small" | "none" | "medium" | "large";
|
|
48
|
+
readonly description: string;
|
|
49
|
+
};
|
|
50
|
+
readonly align: {
|
|
51
|
+
readonly type: import("../index.ts").CompositeType<"center" | "stretch" | "start" | "end" | "baseline">;
|
|
52
|
+
readonly initial: () => "center" | "stretch" | "start" | "end" | "baseline";
|
|
53
|
+
readonly description: string;
|
|
54
|
+
};
|
|
55
|
+
readonly justify: {
|
|
56
|
+
readonly type: import("../index.ts").CompositeType<"center" | "start" | "end" | "space-between" | "space-around">;
|
|
57
|
+
readonly initial: () => "center" | "start" | "end" | "space-between" | "space-around";
|
|
58
|
+
readonly description: string;
|
|
59
|
+
};
|
|
60
|
+
readonly wrap: {
|
|
61
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
62
|
+
readonly initial: () => boolean;
|
|
63
|
+
readonly description: string;
|
|
64
|
+
};
|
|
65
|
+
readonly responsive: {
|
|
66
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
67
|
+
readonly initial: () => boolean;
|
|
68
|
+
readonly description: string;
|
|
69
|
+
};
|
|
70
|
+
readonly content: {
|
|
71
|
+
readonly type: import("../index.ts").CompositeType<View>;
|
|
72
|
+
readonly initial: () => View;
|
|
73
|
+
readonly description: string;
|
|
74
|
+
};
|
|
75
|
+
}>;
|
|
76
|
+
export declare const VerticalLayout: import("../index.ts").DeclaredElement<{
|
|
77
|
+
readonly direction: {
|
|
78
|
+
readonly type: import("../index.ts").CompositeType<"horizontal" | "vertical">;
|
|
79
|
+
readonly initial: () => "horizontal" | "vertical";
|
|
80
|
+
readonly description: string;
|
|
81
|
+
};
|
|
82
|
+
readonly gap: {
|
|
83
|
+
readonly type: import("../index.ts").CompositeType<"small" | "none" | "medium" | "large">;
|
|
84
|
+
readonly initial: () => "small" | "none" | "medium" | "large";
|
|
85
|
+
readonly description: string;
|
|
86
|
+
};
|
|
87
|
+
readonly align: {
|
|
88
|
+
readonly type: import("../index.ts").CompositeType<"center" | "stretch" | "start" | "end" | "baseline">;
|
|
89
|
+
readonly initial: () => "center" | "stretch" | "start" | "end" | "baseline";
|
|
90
|
+
readonly description: string;
|
|
91
|
+
};
|
|
92
|
+
readonly justify: {
|
|
93
|
+
readonly type: import("../index.ts").CompositeType<"center" | "start" | "end" | "space-between" | "space-around">;
|
|
94
|
+
readonly initial: () => "center" | "start" | "end" | "space-between" | "space-around";
|
|
95
|
+
readonly description: string;
|
|
96
|
+
};
|
|
97
|
+
readonly wrap: {
|
|
98
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
99
|
+
readonly initial: () => boolean;
|
|
100
|
+
readonly description: string;
|
|
101
|
+
};
|
|
102
|
+
readonly responsive: {
|
|
103
|
+
readonly type: import("../index.ts").CompositeType<boolean>;
|
|
104
|
+
readonly initial: () => boolean;
|
|
105
|
+
readonly description: string;
|
|
106
|
+
};
|
|
107
|
+
readonly content: {
|
|
108
|
+
readonly type: import("../index.ts").CompositeType<View>;
|
|
109
|
+
readonly initial: () => View;
|
|
110
|
+
readonly description: string;
|
|
111
|
+
};
|
|
112
|
+
}>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { html, nothing } from "lit-html";
|
|
2
|
+
import { defineElement, elementProperty } from "../composition/element.js";
|
|
3
|
+
import { compositeTypes as t } from "../composition/contracts.js";
|
|
4
|
+
const choice = (...values) => t.custom(values.join(" | "), (v) => values.includes(v), { enum: values });
|
|
5
|
+
const content = t.custom("content template", (v) => v === nothing || !!v && typeof v === "object" && "_$litType$" in v);
|
|
6
|
+
const properties = {
|
|
7
|
+
gap: elementProperty(choice("none", "small", "medium", "large"), () => "medium", "gap"),
|
|
8
|
+
align: elementProperty(choice("stretch", "start", "center", "end", "baseline"), () => "stretch", "align"),
|
|
9
|
+
justify: elementProperty(choice("start", "center", "end", "space-between", "space-around"), () => "start", "justify"),
|
|
10
|
+
wrap: elementProperty(t.boolean, () => false, "wrap"),
|
|
11
|
+
responsive: elementProperty(t.boolean, () => true, "responsive"),
|
|
12
|
+
content: elementProperty(content, () => nothing, "content"),
|
|
13
|
+
};
|
|
14
|
+
function stack(tag, direction) {
|
|
15
|
+
return defineElement({ tag, properties: { ...properties, direction: elementProperty(choice("horizontal", "vertical"), () => direction, "Layout direction") },
|
|
16
|
+
render: p => html `<div class="aster-stack" data-direction=${p.direction} data-gap=${p.gap} data-align=${p.align} data-justify=${p.justify} ?data-wrap=${p.wrap} ?data-responsive=${p.responsive}>${p.content}</div>`,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export const Stack = stack("aster-stack", "vertical");
|
|
20
|
+
export const HorizontalLayout = stack("aster-horizontal-layout", "horizontal");
|
|
21
|
+
export const VerticalLayout = stack("aster-vertical-layout", "vertical");
|