ajo-ui 0.1.0
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 +15 -0
- package/README.md +126 -0
- package/dist/accordion.js +130 -0
- package/dist/avatar.js +54 -0
- package/dist/calendar.js +2 -0
- package/dist/carousel.js +239 -0
- package/dist/chart.js +790 -0
- package/dist/checkbox-group.js +70 -0
- package/dist/checkbox.js +77 -0
- package/dist/chunks/bar-CVafh6C1.js +99 -0
- package/dist/chunks/calendar-q8jZ8Cxr.js +1923 -0
- package/dist/chunks/collection-DtRB63U4.js +111 -0
- package/dist/chunks/data-table-DpkWv4y4.js +1039 -0
- package/dist/chunks/menu-B45IyHHC.js +704 -0
- package/dist/chunks/native-BJdhd9XJ.js +20 -0
- package/dist/chunks/popup-C8Bb3l_g.js +459 -0
- package/dist/chunks/popup-surface-BDCgtVU0.js +18 -0
- package/dist/chunks/position-D6_i_SRn.js +434 -0
- package/dist/chunks/virtual-list-B7hjGkjk.js +413 -0
- package/dist/collapsible.js +106 -0
- package/dist/command.js +263 -0
- package/dist/context-menu.js +112 -0
- package/dist/data-table.js +5 -0
- package/dist/dialog.js +207 -0
- package/dist/direction.js +22 -0
- package/dist/drawer.js +139 -0
- package/dist/field.js +26 -0
- package/dist/index.js +38 -0
- package/dist/input-date.js +994 -0
- package/dist/input-group.js +52 -0
- package/dist/input-otp.js +179 -0
- package/dist/menu.js +2 -0
- package/dist/menubar.js +236 -0
- package/dist/message-scroller.js +446 -0
- package/dist/navigation-menu.js +330 -0
- package/dist/popover.js +307 -0
- package/dist/progress.js +39 -0
- package/dist/radio-group.js +107 -0
- package/dist/resizable.js +172 -0
- package/dist/select.js +961 -0
- package/dist/sidebar.js +343 -0
- package/dist/slider.js +259 -0
- package/dist/switch.js +53 -0
- package/dist/tabs.js +182 -0
- package/dist/toast.js +492 -0
- package/dist/toggle-group.js +111 -0
- package/dist/toggle.js +52 -0
- package/dist/toolbar.js +127 -0
- package/dist/tooltip.js +196 -0
- package/dist/utils.js +104 -0
- package/dist/virtual-list.js +2 -0
- package/package.json +250 -0
- package/src/accordion.tsx +261 -0
- package/src/availability.ts +261 -0
- package/src/avatar.tsx +99 -0
- package/src/bar.ts +156 -0
- package/src/calendar.tsx +1441 -0
- package/src/carousel.tsx +424 -0
- package/src/chart.tsx +1194 -0
- package/src/checkbox-group.tsx +132 -0
- package/src/checkbox.tsx +130 -0
- package/src/collapsible.tsx +188 -0
- package/src/collection.ts +154 -0
- package/src/command.tsx +511 -0
- package/src/context-menu.tsx +233 -0
- package/src/data-table-contract.ts +143 -0
- package/src/data-table-model.ts +760 -0
- package/src/data-table.tsx +475 -0
- package/src/dialog.tsx +393 -0
- package/src/direction.tsx +45 -0
- package/src/drawer.tsx +251 -0
- package/src/field.tsx +61 -0
- package/src/index.ts +37 -0
- package/src/input-date.tsx +1539 -0
- package/src/input-group.tsx +142 -0
- package/src/input-otp.tsx +324 -0
- package/src/menu-cluster.ts +124 -0
- package/src/menu.tsx +1095 -0
- package/src/menubar.tsx +459 -0
- package/src/message-scroller.tsx +732 -0
- package/src/native.ts +26 -0
- package/src/navigation-menu.tsx +578 -0
- package/src/popover.tsx +519 -0
- package/src/popup-surface.tsx +31 -0
- package/src/popup.ts +569 -0
- package/src/position.ts +523 -0
- package/src/progress.tsx +70 -0
- package/src/radio-group.tsx +186 -0
- package/src/resizable.tsx +310 -0
- package/src/segments.ts +922 -0
- package/src/select.tsx +1501 -0
- package/src/sidebar.tsx +683 -0
- package/src/slider.tsx +424 -0
- package/src/switch.tsx +104 -0
- package/src/tabs.tsx +314 -0
- package/src/toast.tsx +923 -0
- package/src/toggle-group.tsx +249 -0
- package/src/toggle.tsx +91 -0
- package/src/toolbar.tsx +212 -0
- package/src/tooltip.tsx +359 -0
- package/src/utils.ts +204 -0
- package/src/virtual-list.tsx +205 -0
- package/src/virtual.ts +385 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ariaChecked, bool, flag, syncCheckedState } from "./utils.js";
|
|
2
|
+
import { callHandler, callRef, dom, listen, statefulRootAttrs } from "ajo-cloves";
|
|
3
|
+
import { context } from "ajo/context";
|
|
4
|
+
import { Fragment, jsx, jsxs } from "ajo/jsx-runtime";
|
|
5
|
+
//#region packages/ajo-ui/src/radio-group.tsx
|
|
6
|
+
var RadioGroupContext = context(null);
|
|
7
|
+
var syncRadioInput = (input) => syncCheckedState(input, input.closest("[data-slot=\"radio-group-item\"]"));
|
|
8
|
+
var syncRadioGroup = (root) => {
|
|
9
|
+
for (const input of root.querySelectorAll("input[data-slot=\"radio-group-input\"]")) syncRadioInput(input);
|
|
10
|
+
};
|
|
11
|
+
var itemState = (active, attrs) => bool(active ?? attrs["set:checked"] ?? attrs.checked ?? attrs.defaultChecked) ? "checked" : "unchecked";
|
|
12
|
+
var change = (value, previous, onValueChange) => (event) => {
|
|
13
|
+
callHandler(previous, event);
|
|
14
|
+
const input = event.currentTarget;
|
|
15
|
+
if (input.checked && value != null) onValueChange?.(value, event);
|
|
16
|
+
queueMicrotask(() => {
|
|
17
|
+
const root = input.closest("[data-slot=\"radio-group\"]");
|
|
18
|
+
if (root) syncRadioGroup(root);
|
|
19
|
+
else syncRadioInput(input);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var RadioGroupRoot = function* () {
|
|
23
|
+
listen(this, "change", () => {
|
|
24
|
+
queueMicrotask(() => syncRadioGroup(this));
|
|
25
|
+
});
|
|
26
|
+
for (const { children, defaultValue, disabled, name, onValueChange, required, value } of this) {
|
|
27
|
+
RadioGroupContext({
|
|
28
|
+
defaultValue,
|
|
29
|
+
disabled,
|
|
30
|
+
name,
|
|
31
|
+
onValueChange,
|
|
32
|
+
required,
|
|
33
|
+
value
|
|
34
|
+
});
|
|
35
|
+
if (dom(this)) queueMicrotask(() => syncRadioGroup(this));
|
|
36
|
+
yield /* @__PURE__ */ jsx(Fragment, { children });
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
RadioGroupRoot.is = "fieldset";
|
|
40
|
+
/** Unstyled radio group with native fieldset semantics. */
|
|
41
|
+
var RadioGroup = ({ children, defaultValue, disabled, name, onValueChange, orientation = "vertical", required, value, ...attrs }) => {
|
|
42
|
+
const disabledFlag = disabled ? true : void 0;
|
|
43
|
+
const requiredFlag = required ? true : void 0;
|
|
44
|
+
return /* @__PURE__ */ jsx(RadioGroupRoot, {
|
|
45
|
+
...statefulRootAttrs(attrs),
|
|
46
|
+
defaultValue,
|
|
47
|
+
disabled: disabledFlag,
|
|
48
|
+
name,
|
|
49
|
+
onValueChange,
|
|
50
|
+
required: requiredFlag,
|
|
51
|
+
value,
|
|
52
|
+
"attr:aria-orientation": orientation,
|
|
53
|
+
"attr:data-disabled": flag(disabled),
|
|
54
|
+
"attr:data-orientation": orientation,
|
|
55
|
+
"attr:data-slot": "radio-group",
|
|
56
|
+
"attr:disabled": disabledFlag,
|
|
57
|
+
children
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
/** Unstyled native radio item with indicator slot. */
|
|
61
|
+
var RadioGroupItem = ({ checked, class: classes, disabled, indicatorClass, inputClass, name, ref, required, "set:checked": setChecked, "set:onchange": setOnChange, type: _type, value, ...attrs }) => {
|
|
62
|
+
const group = RadioGroupContext();
|
|
63
|
+
const itemValue = value == null ? void 0 : String(value);
|
|
64
|
+
const ownChecked = checked == null ? void 0 : Boolean(checked);
|
|
65
|
+
const groupChecked = group?.value != null ? itemValue === group.value : group?.defaultValue != null ? itemValue === group.defaultValue : void 0;
|
|
66
|
+
const active = ownChecked ?? groupChecked;
|
|
67
|
+
const syncChecked = active ?? setChecked;
|
|
68
|
+
const state = itemState(active, {
|
|
69
|
+
...attrs,
|
|
70
|
+
checked,
|
|
71
|
+
defaultChecked: attrs.defaultChecked,
|
|
72
|
+
"set:checked": setChecked
|
|
73
|
+
});
|
|
74
|
+
const disabledValue = disabled ?? group?.disabled;
|
|
75
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
76
|
+
class: classes,
|
|
77
|
+
"data-disabled": flag(disabledValue),
|
|
78
|
+
"data-slot": "radio-group-item",
|
|
79
|
+
"data-state": state,
|
|
80
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
81
|
+
...attrs,
|
|
82
|
+
"aria-checked": ariaChecked(state),
|
|
83
|
+
checked: active,
|
|
84
|
+
class: inputClass,
|
|
85
|
+
"data-slot": "radio-group-input",
|
|
86
|
+
"data-state": state,
|
|
87
|
+
disabled: disabledValue,
|
|
88
|
+
name: name ?? group?.name,
|
|
89
|
+
ref: (element) => {
|
|
90
|
+
callRef(ref, element);
|
|
91
|
+
if (element) queueMicrotask(() => syncRadioInput(element));
|
|
92
|
+
},
|
|
93
|
+
required: required ?? group?.required,
|
|
94
|
+
"set:checked": syncChecked,
|
|
95
|
+
"set:onchange": change(itemValue, setOnChange, group?.onValueChange),
|
|
96
|
+
type: "radio",
|
|
97
|
+
value
|
|
98
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
99
|
+
"aria-hidden": "true",
|
|
100
|
+
class: indicatorClass,
|
|
101
|
+
"data-slot": "radio-group-indicator",
|
|
102
|
+
"data-state": state
|
|
103
|
+
})]
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
export { RadioGroup, RadioGroupItem };
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { stlx } from "./utils.js";
|
|
2
|
+
import { clamp, listen, move, statefulRootAttrs } from "ajo-cloves";
|
|
3
|
+
import { context } from "ajo/context";
|
|
4
|
+
import { Fragment, jsx } from "ajo/jsx-runtime";
|
|
5
|
+
//#region packages/ajo-ui/src/resizable.tsx
|
|
6
|
+
/** Layout direction shared by a ResizablePanelGroup with its parts. */
|
|
7
|
+
var ResizableContext = context({ orientation: "horizontal" });
|
|
8
|
+
var percent = (size, fallback) => {
|
|
9
|
+
if (typeof size === "number" && Number.isFinite(size)) return size;
|
|
10
|
+
if (typeof size === "string") {
|
|
11
|
+
const parsed = Number.parseFloat(size);
|
|
12
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
13
|
+
}
|
|
14
|
+
return fallback;
|
|
15
|
+
};
|
|
16
|
+
var limit = (panel, name, fallback) => percent(panel.dataset[name], fallback);
|
|
17
|
+
var style = (orientation, defaultSize, minSize, maxSize, styles) => {
|
|
18
|
+
const basis = percent(defaultSize, 0);
|
|
19
|
+
return stlx(typeof styles === "string" ? styles : void 0, { flex: defaultSize == null ? "1 1 0" : `0 0 ${basis}%` }, minSize == null ? void 0 : { [orientation === "horizontal" ? "minWidth" : "minHeight"]: `${percent(minSize, 0)}%` }, maxSize == null ? void 0 : { [orientation === "horizontal" ? "maxWidth" : "maxHeight"]: `${percent(maxSize, 100)}%` });
|
|
20
|
+
};
|
|
21
|
+
var mainSize = (element, orientation) => {
|
|
22
|
+
const box = element.getBoundingClientRect();
|
|
23
|
+
return orientation === "horizontal" ? box.width : box.height;
|
|
24
|
+
};
|
|
25
|
+
var previousPanel = (handle) => {
|
|
26
|
+
let node = handle.previousElementSibling;
|
|
27
|
+
while (node && !(node instanceof HTMLElement && node.matches("[data-slot=\"resizable-panel\"]"))) node = node.previousElementSibling;
|
|
28
|
+
return node instanceof HTMLElement ? node : null;
|
|
29
|
+
};
|
|
30
|
+
var nextPanel = (handle) => {
|
|
31
|
+
let node = handle.nextElementSibling;
|
|
32
|
+
while (node && !(node instanceof HTMLElement && node.matches("[data-slot=\"resizable-panel\"]"))) node = node.nextElementSibling;
|
|
33
|
+
return node instanceof HTMLElement ? node : null;
|
|
34
|
+
};
|
|
35
|
+
var owningGroup = (handle) => handle.closest("[data-slot=\"resizable-panel-group\"]");
|
|
36
|
+
var setPanelSize = (panel, px, groupSize) => {
|
|
37
|
+
const pct = groupSize > 0 ? px / groupSize * 100 : 0;
|
|
38
|
+
panel.dataset.size = String(pct);
|
|
39
|
+
panel.style.flex = `0 0 ${px}px`;
|
|
40
|
+
panel.dispatchEvent(new CustomEvent("resize", { detail: { size: pct } }));
|
|
41
|
+
};
|
|
42
|
+
var setHandleValue = (session, prev) => {
|
|
43
|
+
const pct = session.groupSize > 0 ? prev / session.groupSize * 100 : 0;
|
|
44
|
+
session.handle.setAttribute("aria-valuenow", String(Math.round(clamp(pct, 0, 100))));
|
|
45
|
+
};
|
|
46
|
+
var applyResize = (session, delta) => {
|
|
47
|
+
const min = Math.max(session.prevMin, session.total - session.nextMax);
|
|
48
|
+
const max = Math.min(session.prevMax, session.total - session.nextMin);
|
|
49
|
+
const prev = clamp(session.prevStart + delta, min, Math.max(min, max));
|
|
50
|
+
const next = session.total - prev;
|
|
51
|
+
setPanelSize(session.prev, prev, session.groupSize);
|
|
52
|
+
setPanelSize(session.next, next, session.groupSize);
|
|
53
|
+
setHandleValue(session, prev);
|
|
54
|
+
};
|
|
55
|
+
var session = (group, handle, orientation) => {
|
|
56
|
+
const prev = previousPanel(handle);
|
|
57
|
+
const next = nextPanel(handle);
|
|
58
|
+
const groupSize = mainSize(group, orientation);
|
|
59
|
+
if (!prev || !next || groupSize <= 0) return null;
|
|
60
|
+
const prevStart = mainSize(prev, orientation);
|
|
61
|
+
const total = prevStart + mainSize(next, orientation);
|
|
62
|
+
const active = {
|
|
63
|
+
groupSize,
|
|
64
|
+
handle,
|
|
65
|
+
next,
|
|
66
|
+
nextMax: groupSize * limit(next, "maxSize", 100) / 100,
|
|
67
|
+
nextMin: groupSize * limit(next, "minSize", 0) / 100,
|
|
68
|
+
prev,
|
|
69
|
+
prevMax: groupSize * limit(prev, "maxSize", 100) / 100,
|
|
70
|
+
prevMin: groupSize * limit(prev, "minSize", 0) / 100,
|
|
71
|
+
prevStart,
|
|
72
|
+
total
|
|
73
|
+
};
|
|
74
|
+
setHandleValue(active, prevStart);
|
|
75
|
+
return active;
|
|
76
|
+
};
|
|
77
|
+
var ResizablePanelGroupRoot = function* () {
|
|
78
|
+
let orientation = "horizontal";
|
|
79
|
+
let active = null;
|
|
80
|
+
let cursor = "";
|
|
81
|
+
let select = "";
|
|
82
|
+
const restore = () => {
|
|
83
|
+
if (!active) return;
|
|
84
|
+
document.body.style.cursor = cursor;
|
|
85
|
+
document.body.style.userSelect = select;
|
|
86
|
+
active = null;
|
|
87
|
+
};
|
|
88
|
+
this.signal.addEventListener("abort", restore, { once: true });
|
|
89
|
+
const drag = move(this, {
|
|
90
|
+
onMove: (data) => {
|
|
91
|
+
if (active) applyResize(active, orientation === "horizontal" ? data.dx : data.dy);
|
|
92
|
+
},
|
|
93
|
+
onEnd: () => restore()
|
|
94
|
+
});
|
|
95
|
+
const startPointer = (event) => {
|
|
96
|
+
if (active || event.button !== 0) return;
|
|
97
|
+
const handle = event.target?.closest("[data-slot=\"resizable-handle\"]");
|
|
98
|
+
if (!handle || owningGroup(handle) !== this || handle.getAttribute("aria-disabled") === "true") return;
|
|
99
|
+
const next = session(this, handle, orientation);
|
|
100
|
+
if (!next) return;
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
event.stopPropagation();
|
|
103
|
+
cursor = document.body.style.cursor;
|
|
104
|
+
select = document.body.style.userSelect;
|
|
105
|
+
document.body.style.cursor = orientation === "horizontal" ? "col-resize" : "row-resize";
|
|
106
|
+
document.body.style.userSelect = "none";
|
|
107
|
+
active = next;
|
|
108
|
+
if (!drag.start(event)) restore();
|
|
109
|
+
};
|
|
110
|
+
const keyResize = (event) => {
|
|
111
|
+
const handle = event.target?.closest("[data-slot=\"resizable-handle\"]");
|
|
112
|
+
if (!handle || owningGroup(handle) !== this || handle.getAttribute("aria-disabled") === "true") return;
|
|
113
|
+
const step = event.shiftKey ? 50 : 10;
|
|
114
|
+
const delta = orientation === "horizontal" ? event.key === "ArrowLeft" ? -step : event.key === "ArrowRight" ? step : 0 : event.key === "ArrowUp" ? -step : event.key === "ArrowDown" ? step : 0;
|
|
115
|
+
if (!delta) return;
|
|
116
|
+
const active = session(this, handle, orientation);
|
|
117
|
+
if (!active) return;
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
applyResize(active, delta);
|
|
120
|
+
};
|
|
121
|
+
listen(this, "pointerdown", startPointer);
|
|
122
|
+
listen(this, "keydown", keyResize);
|
|
123
|
+
for (const args of this) {
|
|
124
|
+
orientation = args.orientation ?? "horizontal";
|
|
125
|
+
ResizableContext({ orientation });
|
|
126
|
+
yield /* @__PURE__ */ jsx(Fragment, { children: args.children });
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
/** Unstyled resizable panel group for split layouts. */
|
|
130
|
+
var ResizablePanelGroup = ({ children, orientation = "horizontal", ...attrs }) => /* @__PURE__ */ jsx(ResizablePanelGroupRoot, {
|
|
131
|
+
...statefulRootAttrs(attrs),
|
|
132
|
+
orientation,
|
|
133
|
+
"attr:aria-orientation": orientation,
|
|
134
|
+
"attr:data-orientation": orientation,
|
|
135
|
+
"attr:data-panel-group-direction": orientation,
|
|
136
|
+
"attr:data-slot": "resizable-panel-group",
|
|
137
|
+
children
|
|
138
|
+
});
|
|
139
|
+
/** Unstyled resizable flex panel. */
|
|
140
|
+
var ResizablePanel = ({ children, defaultSize, maxSize, minSize, style: styles, ...attrs }) => {
|
|
141
|
+
const { orientation } = ResizableContext();
|
|
142
|
+
const initial = percent(defaultSize, 0);
|
|
143
|
+
return /* @__PURE__ */ jsx("div", {
|
|
144
|
+
...attrs,
|
|
145
|
+
"data-max-size": maxSize == null ? void 0 : percent(maxSize, 100),
|
|
146
|
+
"data-min-size": minSize == null ? void 0 : percent(minSize, 0),
|
|
147
|
+
"data-size": defaultSize == null ? void 0 : initial,
|
|
148
|
+
"data-slot": "resizable-panel",
|
|
149
|
+
style: style(orientation, defaultSize, minSize, maxSize, styles),
|
|
150
|
+
children
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
/** Unstyled resize separator between adjacent panels. */
|
|
154
|
+
var ResizableHandle = ({ children, disabled, ...attrs }) => {
|
|
155
|
+
const { orientation } = ResizableContext();
|
|
156
|
+
const separator = orientation === "vertical" ? "horizontal" : "vertical";
|
|
157
|
+
return /* @__PURE__ */ jsx("div", {
|
|
158
|
+
...attrs,
|
|
159
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
160
|
+
"aria-orientation": separator,
|
|
161
|
+
"aria-valuemax": "100",
|
|
162
|
+
"aria-valuemin": "0",
|
|
163
|
+
"data-orientation": separator,
|
|
164
|
+
"data-panel-group-direction": orientation,
|
|
165
|
+
"data-slot": "resizable-handle",
|
|
166
|
+
role: "separator",
|
|
167
|
+
tabindex: disabled ? -1 : 0,
|
|
168
|
+
children
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
//#endregion
|
|
172
|
+
export { ResizableContext, ResizableHandle, ResizablePanel, ResizablePanelGroup };
|