feat: release design system engine, studio and component contracts

This commit is contained in:
Clintchiz committed 2026-10-19 13:09:03 +05:30
1 parent ff1065fb27
commit 3943b946d6
693 files changed
+175546 -3894

No files matched your search

+53 -13
View File
@@ -19,7 +19,10 @@ export function createDndManager(options: DndManagerOptions): DndManager {
}
>();
const manager = new DragDropManager();
const zones = new Map<string | number, { droppable: Droppable; location: { group: string | number; index: number } }>();
const zones = new Map<
string | number,
{ droppable: Droppable; location: { group: string | number; index: number } }
>();
let activeIds: Array<string | number> = [];
let generation = 0;
let destroyed = false;
@@ -27,11 +30,14 @@ export function createDndManager(options: DndManagerOptions): DndManager {
const keyboardAligned = (id: string | number, target: HTMLElement) => {
if (!keyboardAxis) return true;
const element = entries.get(id)?.current.element;
const a = element?.getBoundingClientRect?.(), b = target.getBoundingClientRect?.();
const a = element?.getBoundingClientRect?.(),
b = target.getBoundingClientRect?.();
if (!a || !b) return true;
return keyboardAxis === "x" ? Math.min(a.bottom, b.bottom) > Math.max(a.top, b.top) : Math.min(a.right, b.right) > Math.max(a.left, b.left);
return keyboardAxis === "x"
? Math.min(a.bottom, b.bottom) > Math.max(a.top, b.top)
: Math.min(a.right, b.right) > Math.max(a.left, b.left);
};
manager.monitor.addEventListener("dragmove", event => {
manager.monitor.addEventListener("dragmove", (event) => {
const code = (event.nativeEvent as KeyboardEvent | undefined)?.code;
if (code === "ArrowLeft" || code === "ArrowRight") keyboardAxis = "x";
else if (code === "ArrowUp" || code === "ArrowDown") keyboardAxis = "y";
@@ -54,7 +60,10 @@ export function createDndManager(options: DndManagerOptions): DndManager {
const target = event.operation.target as
(typeof event.operation.target & { group?: string | number; index?: number }) | null;
if (!target) return;
const destination = zones.get(target.id)?.location ?? { group: target.group ?? "default", index: target.index ?? 0 };
const destination = zones.get(target.id)?.location ?? {
group: target.group ?? "default",
index: target.index ?? 0,
};
if (options.accept && !options.accept(activeIds, destination)) {
event.preventDefault();
options.announce?.({ type: "invalid", ids: activeIds, location: destination });
@@ -85,7 +94,11 @@ export function createDndManager(options: DndManagerOptions): DndManager {
index: source.initialIndex ?? source.index ?? 0,
},
],
to: { ...(event.operation.target ? zones.get(event.operation.target.id)?.location : undefined) ?? { group: source.group ?? "default", index: source.index ?? 0 } },
to: {
...((event.operation.target
? zones.get(event.operation.target.id)?.location
: undefined) ?? { group: source.group ?? "default", index: source.index ?? 0 }),
},
};
// A pending commit must not own the next gesture's selection or lifecycle.
activeIds = [];
@@ -113,10 +126,30 @@ export function createDndManager(options: DndManagerOptions): DndManager {
return {
registerDropZone(registration) {
if (destroyed) throw new Error("Cannot register a drop zone after manager destruction.");
if (entries.has(registration.id) || zones.has(registration.id)) throw new Error(`Duplicate draggable or drop zone id ${String(registration.id)}.`);
if (!Number.isSafeInteger(registration.index) || registration.index < 0) throw new Error("Drop zone index must be a non-negative safe integer.");
const droppable = new Droppable({ id: registration.id, element: registration.element, accept: source => keyboardAligned(source.id, registration.element) && (!registration.accepts || registration.accepts.some(type => type === source.type)) && (options.accept?.([source.id], { group: registration.group, index: registration.index }) ?? true), disabled: registration.disabled }, manager);
zones.set(registration.id, { droppable, location: { group: registration.group, index: registration.index } });
if (entries.has(registration.id) || zones.has(registration.id))
throw new Error(`Duplicate draggable or drop zone id ${String(registration.id)}.`);
if (!Number.isSafeInteger(registration.index) || registration.index < 0)
throw new Error("Drop zone index must be a non-negative safe integer.");
const droppable = new Droppable(
{
id: registration.id,
element: registration.element,
accept: (source) =>
keyboardAligned(source.id, registration.element) &&
(!registration.accepts || registration.accepts.some((type) => type === source.type)) &&
(options.accept?.([source.id], {
group: registration.group,
index: registration.index,
}) ??
true),
disabled: registration.disabled,
},
manager,
);
zones.set(registration.id, {
droppable,
location: { group: registration.group, index: registration.index },
});
return () => {
if (zones.get(registration.id)?.droppable !== droppable) return;
droppable.destroy();
@@ -140,10 +173,17 @@ export function createDndManager(options: DndManagerOptions): DndManager {
const origin = entries.get(source.id)?.current.element;
// A nested ancestor overlaps its own descendants and must not steal
// their next keyboard/pointer target just because its box is larger.
if (source.id !== registration.id && origin && registration.element.contains?.(origin)) return false;
if (registration.accepts && !registration.accepts.some(type => type === source.type)) return false;
if (source.id !== registration.id && origin && registration.element.contains?.(origin))
return false;
if (registration.accepts && !registration.accepts.some((type) => type === source.type))
return false;
const target = entries.get(registration.id)?.sortable;
return options.accept?.([source.id], { group: target?.group ?? registration.group, index: target?.index ?? registration.index }) ?? true;
return (
options.accept?.([source.id], {
group: target?.group ?? registration.group,
index: target?.index ?? registration.index,
}) ?? true
);
},
disabled: registration.disabled,
transition: reducedMotion ? null : undefined,