@dou-ui/dashboard 0.1.0-alpha.0 → 0.1.0-alpha.2

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.
@@ -238,10 +238,157 @@ function findPlace(items, size, options) {
238
238
  };
239
239
  }
240
240
  /**
241
+ * Whether a row came out right: every item at least a column wide, none
242
+ * on top of the one before it or past the last column, and items that
243
+ * were equally wide still equally wide.
244
+ */
245
+ function fair(spans, to) {
246
+ const widths = /* @__PURE__ */ new Map();
247
+ return spans.every((span, i) => {
248
+ const prev = spans[i - 1];
249
+ if (span.w < 1 || span.x + span.w > to) return false;
250
+ if (prev && prev.line === span.line && span.x < prev.x + prev.w) return false;
251
+ const w = widths.get(span.item.w);
252
+ if (w === void 0) widths.set(span.item.w, span.w);
253
+ return w === void 0 || w === span.w;
254
+ });
255
+ }
256
+ /** Both edges scaled and rounded, so items side by side stay side by side. */
257
+ function scaled(row, factor) {
258
+ const edge = (value) => Math.round(value * factor);
259
+ return row.map((item) => {
260
+ const x = edge(item.x);
261
+ return {
262
+ item,
263
+ x,
264
+ w: edge(item.x + item.w) - x,
265
+ line: 0,
266
+ factor
267
+ };
268
+ });
269
+ }
270
+ /**
271
+ * The row wrapped onto as few lines as keep its items equally wide, at
272
+ * most `most`. Items are packed left to right without the gaps between
273
+ * them, each line holding the same number of source columns at most, the
274
+ * fullest line filling the grid. At least one line holds two items or
275
+ * more, so items never end up one per line. Widths are rounded down,
276
+ * leaving columns empty, when no number of lines keeps them equal otherwise.
277
+ */
278
+ function wrapped(row, to, most) {
279
+ const total = row.reduce((sum, item) => sum + item.w, 0);
280
+ const pack = (size) => {
281
+ const lines = [];
282
+ let used = Infinity;
283
+ for (const item of row) {
284
+ if (used + item.w > size) {
285
+ lines.push([]);
286
+ used = 0;
287
+ }
288
+ lines[lines.length - 1].push(item);
289
+ used += item.w;
290
+ }
291
+ return lines;
292
+ };
293
+ const options = /* @__PURE__ */ new Map();
294
+ for (let size = Math.max(...row.map((item) => item.w)); size < total; size++) {
295
+ const lines = pack(size);
296
+ if (lines.length <= most && lines.length < row.length && !options.has(lines.length)) options.set(lines.length, {
297
+ lines,
298
+ size
299
+ });
300
+ }
301
+ const counts = [...options.keys()];
302
+ counts.sort((a, b) => a - b);
303
+ for (const down of [false, true]) for (const count of counts) {
304
+ const { lines, size } = options.get(count);
305
+ const factor = to / size;
306
+ const spans = [];
307
+ for (const [line, items] of lines.entries()) {
308
+ let start = 0;
309
+ let end = 0;
310
+ for (const item of items) {
311
+ const x = down ? end : Math.round(start * factor);
312
+ start += item.w;
313
+ const w = down ? Math.floor(item.w * factor) : Math.round(start * factor) - x;
314
+ end = x + w;
315
+ spans.push({
316
+ item,
317
+ x,
318
+ w,
319
+ line,
320
+ factor
321
+ });
322
+ }
323
+ }
324
+ if (fair(spans, to)) return spans;
325
+ }
326
+ }
327
+ /**
328
+ * The row kept on one line, items that share a width given the same
329
+ * number of columns: rounded to the nearest when they fit, otherwise
330
+ * rounded down. Items that touched still touch, so the columns left empty
331
+ * gather at the end; items with a gap between them stay near where they
332
+ * were, moved left only as far as it takes to fit.
333
+ */
334
+ function oneLine(row, scale, to) {
335
+ const shared = /* @__PURE__ */ new Map();
336
+ for (const item of row) shared.set(item.w, (shared.get(item.w) ?? 0) + 1);
337
+ for (const round of [Math.round, Math.floor]) {
338
+ const spans = [];
339
+ for (const item of row) {
340
+ const prev = spans[spans.length - 1];
341
+ const x = !prev ? Math.round(item.x * scale) : prev.item.x + prev.item.w === item.x ? prev.x + prev.w : Math.max(Math.round(item.x * scale), prev.x + prev.w);
342
+ const w = (shared.get(item.w) > 1 ? round : Math.round)(item.w * scale);
343
+ spans.push({
344
+ item,
345
+ x,
346
+ w,
347
+ line: 0,
348
+ factor: scale
349
+ });
350
+ }
351
+ let end = to;
352
+ for (let i = spans.length - 1; i >= 0; i--) {
353
+ const span = spans[i];
354
+ span.x = Math.min(span.x, end - span.w);
355
+ end = span.x;
356
+ }
357
+ if (end >= 0 && fair(spans, to)) return spans;
358
+ }
359
+ }
360
+ /**
361
+ * One row (items sharing a `y`, left to right) on `to` columns, keeping
362
+ * equally wide items equally wide. In order of preference: scaled as is;
363
+ * wrapped onto two lines; kept on one line; wrapped onto more lines. The
364
+ * widths are rounded to the nearest column when that keeps them equal and
365
+ * rounded down otherwise, leaving columns empty. Rows
366
+ * only wrap when the grid gets narrower and the row is a band of its own
367
+ * (all its items equally tall, nothing else reaching into it). Rounded as
368
+ * before when none of that works.
369
+ */
370
+ function scaleRow(row, band, from, to) {
371
+ const scale = to / from;
372
+ const spans = scaled(row, scale);
373
+ if (fair(spans, to)) return spans;
374
+ const wraps = band && to < from;
375
+ const two = wraps ? wrapped(row, to, 2) : void 0;
376
+ if (two) return two;
377
+ const one = oneLine(row, scale, to);
378
+ if (one) return one;
379
+ return (wraps ? wrapped(row, to, row.length) : void 0) ?? spans.map((span) => ({
380
+ ...span,
381
+ w: Math.max(1, span.w)
382
+ }));
383
+ }
384
+ /** A `minW` or `maxW` scaled with the item. */
385
+ var limit = (value, factor) => value === void 0 ? void 0 : Math.max(1, Math.round(value * factor));
386
+ /**
241
387
  * The layout worked out for a grid of another width: positions and widths
242
- * scaled by the ratio of the columns, then settled. On a single column the
243
- * items are stacked in reading order (top to bottom, then left to right),
244
- * each keeping its height.
388
+ * scaled by the ratio of the columns, then settled. Items in a row that
389
+ * were equally wide stay equally wide, by wrapping the row or leaving
390
+ * columns empty (see the docs). On a single column the items are stacked
391
+ * in reading order (top to bottom, then left to right), each keeping its height.
245
392
  */
246
393
  function deriveLayout(items, from, options) {
247
394
  const to = options.columns;
@@ -265,19 +412,32 @@ function deriveLayout(items, from, options) {
265
412
  }
266
413
  return out;
267
414
  }
268
- const scale = to / from;
269
- const edge = (value) => Math.round(value * scale);
270
- const limit = (value) => value === void 0 ? void 0 : Math.max(1, edge(value));
271
- return normalizeLayout(items.map((item) => {
272
- const x = edge(item.x);
273
- return fitItem({
274
- ...item,
275
- x,
276
- w: Math.max(1, edge(item.x + item.w) - x),
277
- minW: limit(item.minW),
278
- maxW: limit(item.maxW)
279
- }, to);
280
- }), options);
415
+ const rows = /* @__PURE__ */ new Map();
416
+ for (const item of items) {
417
+ const row = rows.get(item.y);
418
+ if (row) row.push(item);
419
+ else rows.set(item.y, [item]);
420
+ }
421
+ const ys = [...rows.keys()];
422
+ ys.sort((a, b) => a - b);
423
+ const placed = /* @__PURE__ */ new Map();
424
+ let shift = 0;
425
+ for (const y of ys) {
426
+ const row = rows.get(y);
427
+ row.sort((a, b) => a.x - b.x);
428
+ const h = row[0].h;
429
+ const spans = scaleRow(row, row.every((item) => item.h === h) && items.every((item) => item.y === y || item.y + item.h <= y || item.y >= y + h), from, to);
430
+ for (const span of spans) placed.set(span.item, fitItem({
431
+ ...span.item,
432
+ x: span.x,
433
+ y: y + shift + span.line * h,
434
+ w: span.w,
435
+ minW: limit(span.item.minW, span.factor),
436
+ maxW: limit(span.item.maxW, span.factor)
437
+ }, to));
438
+ shift += spans[spans.length - 1].line * h;
439
+ }
440
+ return normalizeLayout(items.map((item) => placed.get(item)), options);
281
441
  }
282
442
  export { compactLayout, deriveLayout, findPlace, fitItem, layoutHeight, moveItem, moveItemBy, normalizeLayout, overlaps, resizeItem, resizeItemBy };
283
443
 
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","names":[],"sources":["../../src/layout/engine.ts"],"sourcesContent":["import type { GridItem, GridLayoutOptions, GridPosition, GridSize } from './types'\n\n/*\n * The layout engine: plain functions from a layout to a layout.\n *\n * Every function returns a new array in the same order as the one it was\n * given, and keeps the objects of the items that did not move, so a caller\n * can tell what changed by identity. The same input always gives the same\n * output: the order items are settled in depends only on their positions\n * and their places in the array, which is what lets several people editing\n * the same layout end up with the same result.\n */\n\ntype Box = Pick<GridItem, 'x' | 'y' | 'w' | 'h'>\n\n/** Whether two boxes share at least one cell. */\nexport function overlaps(a: Box, b: Box): boolean {\n return a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h\n}\n\n/** The row just below the lowest item: how many rows the layout takes up. */\nexport function layoutHeight(items: readonly Box[]): number {\n let bottom = 0\n for (const item of items) bottom = Math.max(bottom, item.y + item.h)\n return bottom\n}\n\nconst int = (value: number, fallback: number) =>\n Number.isFinite(value) ? Math.round(value) : fallback\n\n/** The width an item may have on a grid of `columns`. */\nfunction clampW(item: GridItem, w: number, columns: number) {\n const max = Math.min(columns, item.maxW ?? columns)\n const min = Math.min(max, Math.max(1, item.minW ?? 1))\n return Math.min(max, Math.max(min, int(w, min)))\n}\n\nfunction clampH(item: GridItem, h: number) {\n const max = Math.max(1, item.maxH ?? Infinity)\n const min = Math.min(max, Math.max(1, item.minH ?? 1))\n return Math.min(max, Math.max(min, int(h, min)))\n}\n\n/**\n * The item with its size inside its limits and the grid's width, and its\n * position on the grid, in whole cells. Returns the item itself when it fits.\n */\nexport function fitItem(item: GridItem, columns: number): GridItem {\n const w = clampW(item, item.w, columns)\n const h = clampH(item, item.h)\n const x = Math.min(columns - w, Math.max(0, int(item.x, 0)))\n const y = Math.max(0, int(item.y, 0))\n return x === item.x && y === item.y && w === item.w && h === item.h\n ? item\n : { ...item, x, y, w, h }\n}\n\nconst at = (item: GridItem, x: number, y: number): GridItem =>\n item.x === x && item.y === y ? item : { ...item, x, y }\n\n/**\n * Where an item the moved one landed on could step aside to: the same\n * row, shifted into the columns the moved item left. This is what turns\n * dropping an item onto its neighbour into a swap, instead of pushing the\n * neighbour down. `undefined` when the item isn't in the way, or wouldn't\n * fit in those columns.\n */\nfunction aside(item: GridItem, fixed?: GridItem, origin?: Box): number | undefined {\n if (!fixed || !origin || !overlaps(item, fixed)) return undefined\n const hi = origin.x + origin.w - item.w\n if (hi < origin.x) return undefined\n const x = Math.min(hi, Math.max(origin.x, item.x))\n return x === item.x ? undefined : x\n}\n\n/** The first of `boxes` that shares a cell with the box, if any. */\nfunction hit(boxes: readonly Box[], box: Box): Box | undefined {\n for (const other of boxes) if (overlaps(other, box)) return other\n return undefined\n}\n\n/** Moves the box down until it is clear of every one of `boxes`; returns its row. */\nfunction below(boxes: readonly Box[], box: Box): number {\n const probe = { ...box }\n for (let other = hit(boxes, probe); other; other = hit(boxes, probe)) probe.y = other.y + other.h\n return probe.y\n}\n\n/**\n * Settles every item that isn't locked and isn't `fixed`; those stay where\n * they are and the rest go around them. Items are settled from the top\n * down (then left to right, then by their place in the array).\n */\nfunction settle(\n items: readonly GridItem[],\n options: GridLayoutOptions,\n fixed?: GridItem,\n origin?: Box,\n): GridItem[] {\n const out = items.slice()\n const obstacles: GridItem[] = []\n const order: number[] = []\n items.forEach((item, i) => {\n if (item.locked || item === fixed) obstacles.push(item)\n else order.push(i)\n })\n order.sort((a, b) => items[a]!.y - items[b]!.y || items[a]!.x - items[b]!.x || a - b)\n\n if (options.compact === false) {\n // Each item keeps its row unless something settled before it is in the way.\n const placed = obstacles.slice()\n for (const i of order) {\n const item = items[i]!\n let x = item.x\n let y = below(placed, item)\n const side = aside(item, fixed, origin)\n if (side !== undefined && !hit(placed, { ...item, x: side })) [x, y] = [side, item.y]\n placed.push((out[i] = at(item, x, y)))\n }\n return out\n }\n\n // `top[c]` is the row below everything settled so far in column `c`: an\n // item can float up to the lowest of these across its columns, which is\n // as far as it can go without passing an item that was above it.\n const top = new Int32Array(options.columns)\n for (const i of order) {\n const item = items[i]!\n const rise = (x: number) => {\n let y = 0\n for (let c = x; c < x + item.w; c++) y = Math.max(y, top[c] ?? 0)\n return below(obstacles, { x, y, w: item.w, h: item.h })\n }\n let x = item.x\n let y = rise(x)\n const side = aside(item, fixed, origin)\n if (side !== undefined) {\n const y2 = rise(side)\n if (y2 < y) [x, y] = [side, y2]\n }\n for (let c = x; c < x + item.w; c++) top[c] = y + item.h\n out[i] = at(item, x, y)\n }\n return out\n}\n\n/**\n * The layout fitted to the grid: sizes inside their limits, nothing past\n * the last column, no two items on the same cell and, when compacting,\n * no gaps above items. Returns `items` itself when it is already settled.\n */\nexport function normalizeLayout(\n items: readonly GridItem[],\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const fitted = items.map((item) => fitItem(item, options.columns))\n const out = settle(fitted, options)\n return out.every((item, i) => item === items[i]) ? items : out\n}\n\n/** Floats every item up as far as it goes (ignores `compact`). */\nexport function compactLayout(items: readonly GridItem[], columns: number): GridItem[] {\n return settle(items, { columns, compact: 'vertical' })\n}\n\n/** Puts `item` at the given place, moved down below any locked item it lands on. */\nfunction place(\n items: readonly GridItem[],\n index: number,\n next: GridItem,\n options: GridLayoutOptions,\n): GridItem[] {\n const locked = items.filter((other) => other.locked && other !== items[index])\n const y = below(locked, next)\n const out = items.slice()\n const moved = (out[index] = at(next, next.x, y))\n const settled = settle(out, options, moved, items[index])\n // Compacting a second time lets the item itself float up into the gap\n // it would otherwise leave, and puts it after the items it was dropped below.\n return options.compact === false ? settled : settle(settled, options)\n}\n\n/**\n * Moves an item to a cell; the items it lands on make way. Locked items\n * and unknown ids leave the layout as it is.\n */\nexport function moveItem(\n items: readonly GridItem[],\n id: string,\n to: GridPosition,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const index = items.findIndex((item) => item.id === id)\n const item = items[index]\n if (!item || item.locked) return items\n const x = Math.min(options.columns - item.w, Math.max(0, int(to.x, item.x)))\n const y = Math.max(0, int(to.y, item.y))\n return place(items, index, { ...item, x, y }, options)\n}\n\n/**\n * Gives an item a new size, keeping its top-left corner; the items it now\n * covers make way. A size that would cover a locked item is refused.\n */\nexport function resizeItem(\n items: readonly GridItem[],\n id: string,\n to: GridSize,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const index = items.findIndex((item) => item.id === id)\n const item = items[index]\n if (!item || item.locked) return items\n const w = Math.min(options.columns - item.x, clampW(item, to.w, options.columns))\n const h = clampH(item, to.h)\n const next = { ...item, w: Math.max(1, w), h }\n if (items.some((other) => other.locked && other !== item && overlaps(other, next))) return items\n return place(items, index, next, options)\n}\n\nconst sameSpot = (a: GridItem | undefined, b: GridItem) =>\n !!a && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h\n\n/**\n * Moves an item by whole cells, as the arrow keys do. Moving up or down\n * goes on past rows where the item would only settle back where it was,\n * so one press always moves it, to the next place it can take.\n */\nexport function moveItemBy(\n items: readonly GridItem[],\n id: string,\n dx: number,\n dy: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const item = items.find((other) => other.id === id)\n if (!item || item.locked) return items\n if (!dy) return moveItem(items, id, { x: item.x + dx, y: item.y }, options)\n const step = Math.sign(dy)\n const last = layoutHeight(items)\n for (let y = item.y + dy; y >= 0 && y <= last; y += step) {\n const out = moveItem(items, id, { x: item.x + dx, y }, options)\n if (\n !sameSpot(\n out.find((other) => other.id === id),\n item,\n )\n )\n return out\n }\n return items\n}\n\n/** Resizes an item by whole cells, as Shift and the arrow keys do. */\nexport function resizeItemBy(\n items: readonly GridItem[],\n id: string,\n dw: number,\n dh: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const item = items.find((other) => other.id === id)\n if (!item) return items\n return resizeItem(items, id, { w: item.w + dw, h: item.h + dh }, options)\n}\n\n/**\n * Where a new item of `size` fits: the first free spot reading from the top\n * left, or below everything when no row has room.\n */\nexport function findPlace(\n items: readonly GridItem[],\n size: GridSize,\n options: GridLayoutOptions,\n): GridPosition {\n const w = Math.min(options.columns, Math.max(1, Math.round(size.w)))\n const h = Math.max(1, Math.round(size.h))\n const bottom = layoutHeight(items)\n for (let y = 0; y < bottom; y++)\n for (let x = 0; x + w <= options.columns; x++) {\n const other = hit(items, { x, y, w, h })\n if (!other) return { x, y }\n // skip to the column after the item in the way\n x = other.x + other.w - 1\n }\n return { x: 0, y: bottom }\n}\n\n/**\n * The layout worked out for a grid of another width: positions and widths\n * scaled by the ratio of the columns, then settled. On a single column the\n * items are stacked in reading order (top to bottom, then left to right),\n * each keeping its height.\n */\nexport function deriveLayout(\n items: readonly GridItem[],\n from: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const to = options.columns\n if (from === to) return normalizeLayout(items, options)\n if (to === 1) {\n const order = items.map((_, i) => i)\n order.sort((a, b) => items[a]!.y - items[b]!.y || items[a]!.x - items[b]!.x || a - b)\n const out = items.slice()\n let y = 0\n for (const i of order) {\n const item = fitItem({ ...items[i]!, x: 0, w: 1 }, 1)\n out[i] = { ...item, y }\n y += item.h\n }\n return out\n }\n const scale = to / from\n // both edges are scaled, so items side by side stay side by side\n const edge = (value: number) => Math.round(value * scale)\n const limit = (value: number | undefined) =>\n value === undefined ? undefined : Math.max(1, edge(value))\n const scaled = items.map((item) => {\n const x = edge(item.x)\n return fitItem(\n {\n ...item,\n x,\n w: Math.max(1, edge(item.x + item.w) - x),\n minW: limit(item.minW),\n maxW: limit(item.maxW),\n },\n to,\n )\n })\n return normalizeLayout(scaled, options)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","names":[],"sources":["../../src/layout/engine.ts"],"sourcesContent":["import type { GridItem, GridLayoutOptions, GridPosition, GridSize } from './types'\n\n/*\n * The layout engine: plain functions from a layout to a layout.\n *\n * Every function returns a new array in the same order as the one it was\n * given, and keeps the objects of the items that did not move, so a caller\n * can tell what changed by identity. The same input always gives the same\n * output: the order items are settled in depends only on their positions\n * and their places in the array, which is what lets several people editing\n * the same layout end up with the same result.\n */\n\ntype Box = Pick<GridItem, 'x' | 'y' | 'w' | 'h'>\n\n/** Whether two boxes share at least one cell. */\nexport function overlaps(a: Box, b: Box): boolean {\n return a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h\n}\n\n/** The row just below the lowest item: how many rows the layout takes up. */\nexport function layoutHeight(items: readonly Box[]): number {\n let bottom = 0\n for (const item of items) bottom = Math.max(bottom, item.y + item.h)\n return bottom\n}\n\nconst int = (value: number, fallback: number) =>\n Number.isFinite(value) ? Math.round(value) : fallback\n\n/** The width an item may have on a grid of `columns`. */\nfunction clampW(item: GridItem, w: number, columns: number) {\n const max = Math.min(columns, item.maxW ?? columns)\n const min = Math.min(max, Math.max(1, item.minW ?? 1))\n return Math.min(max, Math.max(min, int(w, min)))\n}\n\nfunction clampH(item: GridItem, h: number) {\n const max = Math.max(1, item.maxH ?? Infinity)\n const min = Math.min(max, Math.max(1, item.minH ?? 1))\n return Math.min(max, Math.max(min, int(h, min)))\n}\n\n/**\n * The item with its size inside its limits and the grid's width, and its\n * position on the grid, in whole cells. Returns the item itself when it fits.\n */\nexport function fitItem(item: GridItem, columns: number): GridItem {\n const w = clampW(item, item.w, columns)\n const h = clampH(item, item.h)\n const x = Math.min(columns - w, Math.max(0, int(item.x, 0)))\n const y = Math.max(0, int(item.y, 0))\n return x === item.x && y === item.y && w === item.w && h === item.h\n ? item\n : { ...item, x, y, w, h }\n}\n\nconst at = (item: GridItem, x: number, y: number): GridItem =>\n item.x === x && item.y === y ? item : { ...item, x, y }\n\n/**\n * Where an item the moved one landed on could step aside to: the same\n * row, shifted into the columns the moved item left. This is what turns\n * dropping an item onto its neighbour into a swap, instead of pushing the\n * neighbour down. `undefined` when the item isn't in the way, or wouldn't\n * fit in those columns.\n */\nfunction aside(item: GridItem, fixed?: GridItem, origin?: Box): number | undefined {\n if (!fixed || !origin || !overlaps(item, fixed)) return undefined\n const hi = origin.x + origin.w - item.w\n if (hi < origin.x) return undefined\n const x = Math.min(hi, Math.max(origin.x, item.x))\n return x === item.x ? undefined : x\n}\n\n/** The first of `boxes` that shares a cell with the box, if any. */\nfunction hit(boxes: readonly Box[], box: Box): Box | undefined {\n for (const other of boxes) if (overlaps(other, box)) return other\n return undefined\n}\n\n/** Moves the box down until it is clear of every one of `boxes`; returns its row. */\nfunction below(boxes: readonly Box[], box: Box): number {\n const probe = { ...box }\n for (let other = hit(boxes, probe); other; other = hit(boxes, probe)) probe.y = other.y + other.h\n return probe.y\n}\n\n/**\n * Settles every item that isn't locked and isn't `fixed`; those stay where\n * they are and the rest go around them. Items are settled from the top\n * down (then left to right, then by their place in the array).\n */\nfunction settle(\n items: readonly GridItem[],\n options: GridLayoutOptions,\n fixed?: GridItem,\n origin?: Box,\n): GridItem[] {\n const out = items.slice()\n const obstacles: GridItem[] = []\n const order: number[] = []\n items.forEach((item, i) => {\n if (item.locked || item === fixed) obstacles.push(item)\n else order.push(i)\n })\n order.sort((a, b) => items[a]!.y - items[b]!.y || items[a]!.x - items[b]!.x || a - b)\n\n if (options.compact === false) {\n // Each item keeps its row unless something settled before it is in the way.\n const placed = obstacles.slice()\n for (const i of order) {\n const item = items[i]!\n let x = item.x\n let y = below(placed, item)\n const side = aside(item, fixed, origin)\n if (side !== undefined && !hit(placed, { ...item, x: side })) [x, y] = [side, item.y]\n placed.push((out[i] = at(item, x, y)))\n }\n return out\n }\n\n // `top[c]` is the row below everything settled so far in column `c`: an\n // item can float up to the lowest of these across its columns, which is\n // as far as it can go without passing an item that was above it.\n const top = new Int32Array(options.columns)\n for (const i of order) {\n const item = items[i]!\n const rise = (x: number) => {\n let y = 0\n for (let c = x; c < x + item.w; c++) y = Math.max(y, top[c] ?? 0)\n return below(obstacles, { x, y, w: item.w, h: item.h })\n }\n let x = item.x\n let y = rise(x)\n const side = aside(item, fixed, origin)\n if (side !== undefined) {\n const y2 = rise(side)\n if (y2 < y) [x, y] = [side, y2]\n }\n for (let c = x; c < x + item.w; c++) top[c] = y + item.h\n out[i] = at(item, x, y)\n }\n return out\n}\n\n/**\n * The layout fitted to the grid: sizes inside their limits, nothing past\n * the last column, no two items on the same cell and, when compacting,\n * no gaps above items. Returns `items` itself when it is already settled.\n */\nexport function normalizeLayout(\n items: readonly GridItem[],\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const fitted = items.map((item) => fitItem(item, options.columns))\n const out = settle(fitted, options)\n return out.every((item, i) => item === items[i]) ? items : out\n}\n\n/** Floats every item up as far as it goes (ignores `compact`). */\nexport function compactLayout(items: readonly GridItem[], columns: number): GridItem[] {\n return settle(items, { columns, compact: 'vertical' })\n}\n\n/** Puts `item` at the given place, moved down below any locked item it lands on. */\nfunction place(\n items: readonly GridItem[],\n index: number,\n next: GridItem,\n options: GridLayoutOptions,\n): GridItem[] {\n const locked = items.filter((other) => other.locked && other !== items[index])\n const y = below(locked, next)\n const out = items.slice()\n const moved = (out[index] = at(next, next.x, y))\n const settled = settle(out, options, moved, items[index])\n // Compacting a second time lets the item itself float up into the gap\n // it would otherwise leave, and puts it after the items it was dropped below.\n return options.compact === false ? settled : settle(settled, options)\n}\n\n/**\n * Moves an item to a cell; the items it lands on make way. Locked items\n * and unknown ids leave the layout as it is.\n */\nexport function moveItem(\n items: readonly GridItem[],\n id: string,\n to: GridPosition,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const index = items.findIndex((item) => item.id === id)\n const item = items[index]\n if (!item || item.locked) return items\n const x = Math.min(options.columns - item.w, Math.max(0, int(to.x, item.x)))\n const y = Math.max(0, int(to.y, item.y))\n return place(items, index, { ...item, x, y }, options)\n}\n\n/**\n * Gives an item a new size, keeping its top-left corner; the items it now\n * covers make way. A size that would cover a locked item is refused.\n */\nexport function resizeItem(\n items: readonly GridItem[],\n id: string,\n to: GridSize,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const index = items.findIndex((item) => item.id === id)\n const item = items[index]\n if (!item || item.locked) return items\n const w = Math.min(options.columns - item.x, clampW(item, to.w, options.columns))\n const h = clampH(item, to.h)\n const next = { ...item, w: Math.max(1, w), h }\n if (items.some((other) => other.locked && other !== item && overlaps(other, next))) return items\n return place(items, index, next, options)\n}\n\nconst sameSpot = (a: GridItem | undefined, b: GridItem) =>\n !!a && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h\n\n/**\n * Moves an item by whole cells, as the arrow keys do. Moving up or down\n * goes on past rows where the item would only settle back where it was,\n * so one press always moves it, to the next place it can take.\n */\nexport function moveItemBy(\n items: readonly GridItem[],\n id: string,\n dx: number,\n dy: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const item = items.find((other) => other.id === id)\n if (!item || item.locked) return items\n if (!dy) return moveItem(items, id, { x: item.x + dx, y: item.y }, options)\n const step = Math.sign(dy)\n const last = layoutHeight(items)\n for (let y = item.y + dy; y >= 0 && y <= last; y += step) {\n const out = moveItem(items, id, { x: item.x + dx, y }, options)\n if (\n !sameSpot(\n out.find((other) => other.id === id),\n item,\n )\n )\n return out\n }\n return items\n}\n\n/** Resizes an item by whole cells, as Shift and the arrow keys do. */\nexport function resizeItemBy(\n items: readonly GridItem[],\n id: string,\n dw: number,\n dh: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const item = items.find((other) => other.id === id)\n if (!item) return items\n return resizeItem(items, id, { w: item.w + dw, h: item.h + dh }, options)\n}\n\n/**\n * Where a new item of `size` fits: the first free spot reading from the top\n * left, or below everything when no row has room.\n */\nexport function findPlace(\n items: readonly GridItem[],\n size: GridSize,\n options: GridLayoutOptions,\n): GridPosition {\n const w = Math.min(options.columns, Math.max(1, Math.round(size.w)))\n const h = Math.max(1, Math.round(size.h))\n const bottom = layoutHeight(items)\n for (let y = 0; y < bottom; y++)\n for (let x = 0; x + w <= options.columns; x++) {\n const other = hit(items, { x, y, w, h })\n if (!other) return { x, y }\n // skip to the column after the item in the way\n x = other.x + other.w - 1\n }\n return { x: 0, y: bottom }\n}\n\ninterface Span {\n item: GridItem\n x: number\n w: number\n /** Line within the row, 0 when the row didn't wrap. */\n line: number\n /** What the item's width was scaled by, for its `minW` and `maxW`. */\n factor: number\n}\n\n/**\n * Whether a row came out right: every item at least a column wide, none\n * on top of the one before it or past the last column, and items that\n * were equally wide still equally wide.\n */\nfunction fair(spans: readonly Span[], to: number) {\n const widths = new Map<number, number>()\n return spans.every((span, i) => {\n const prev = spans[i - 1]\n if (span.w < 1 || span.x + span.w > to) return false\n if (prev && prev.line === span.line && span.x < prev.x + prev.w) return false\n const w = widths.get(span.item.w)\n if (w === undefined) widths.set(span.item.w, span.w)\n return w === undefined || w === span.w\n })\n}\n\n/** Both edges scaled and rounded, so items side by side stay side by side. */\nfunction scaled(row: readonly GridItem[], factor: number): Span[] {\n const edge = (value: number) => Math.round(value * factor)\n return row.map((item) => {\n const x = edge(item.x)\n return { item, x, w: edge(item.x + item.w) - x, line: 0, factor }\n })\n}\n\n/**\n * The row wrapped onto as few lines as keep its items equally wide, at\n * most `most`. Items are packed left to right without the gaps between\n * them, each line holding the same number of source columns at most, the\n * fullest line filling the grid. At least one line holds two items or\n * more, so items never end up one per line. Widths are rounded down,\n * leaving columns empty, when no number of lines keeps them equal otherwise.\n */\nfunction wrapped(row: readonly GridItem[], to: number, most: number): Span[] | undefined {\n const total = row.reduce((sum, item) => sum + item.w, 0)\n const pack = (size: number) => {\n const lines: GridItem[][] = []\n let used = Infinity\n for (const item of row) {\n if (used + item.w > size) {\n lines.push([])\n used = 0\n }\n lines[lines.length - 1]!.push(item)\n used += item.w\n }\n return lines\n }\n // the smallest size for each number of lines balances the lines best\n const options = new Map<number, { lines: GridItem[][]; size: number }>()\n for (let size = Math.max(...row.map((item) => item.w)); size < total; size++) {\n const lines = pack(size)\n if (lines.length <= most && lines.length < row.length && !options.has(lines.length))\n options.set(lines.length, { lines, size })\n }\n const counts = [...options.keys()]\n counts.sort((a, b) => a - b)\n for (const down of [false, true])\n for (const count of counts) {\n const { lines, size } = options.get(count)!\n const factor = to / size\n const spans: Span[] = []\n for (const [line, items] of lines.entries()) {\n let start = 0\n let end = 0\n for (const item of items) {\n const x = down ? end : Math.round(start * factor)\n start += item.w\n const w = down ? Math.floor(item.w * factor) : Math.round(start * factor) - x\n end = x + w\n spans.push({ item, x, w, line, factor })\n }\n }\n if (fair(spans, to)) return spans\n }\n return undefined\n}\n\n/**\n * The row kept on one line, items that share a width given the same\n * number of columns: rounded to the nearest when they fit, otherwise\n * rounded down. Items that touched still touch, so the columns left empty\n * gather at the end; items with a gap between them stay near where they\n * were, moved left only as far as it takes to fit.\n */\nfunction oneLine(row: readonly GridItem[], scale: number, to: number): Span[] | undefined {\n const shared = new Map<number, number>()\n for (const item of row) shared.set(item.w, (shared.get(item.w) ?? 0) + 1)\n for (const round of [Math.round, Math.floor]) {\n const spans: Span[] = []\n for (const item of row) {\n const prev = spans[spans.length - 1]\n // items that touched still touch, so empty columns gather at the end\n const x = !prev\n ? Math.round(item.x * scale)\n : prev.item.x + prev.item.w === item.x\n ? prev.x + prev.w\n : Math.max(Math.round(item.x * scale), prev.x + prev.w)\n const w = (shared.get(item.w)! > 1 ? round : Math.round)(item.w * scale)\n spans.push({ item, x, w, line: 0, factor: scale })\n }\n let end = to\n for (let i = spans.length - 1; i >= 0; i--) {\n const span = spans[i]!\n span.x = Math.min(span.x, end - span.w)\n end = span.x\n }\n if (end >= 0 && fair(spans, to)) return spans\n }\n return undefined\n}\n\n/**\n * One row (items sharing a `y`, left to right) on `to` columns, keeping\n * equally wide items equally wide. In order of preference: scaled as is;\n * wrapped onto two lines; kept on one line; wrapped onto more lines. The\n * widths are rounded to the nearest column when that keeps them equal and\n * rounded down otherwise, leaving columns empty. Rows\n * only wrap when the grid gets narrower and the row is a band of its own\n * (all its items equally tall, nothing else reaching into it). Rounded as\n * before when none of that works.\n */\nfunction scaleRow(row: readonly GridItem[], band: boolean, from: number, to: number): Span[] {\n const scale = to / from\n const spans = scaled(row, scale)\n if (fair(spans, to)) return spans\n const wraps = band && to < from\n const two = wraps ? wrapped(row, to, 2) : undefined\n if (two) return two\n const one = oneLine(row, scale, to)\n if (one) return one\n const more = wraps ? wrapped(row, to, row.length) : undefined\n return more ?? spans.map((span) => ({ ...span, w: Math.max(1, span.w) }))\n}\n\n/** A `minW` or `maxW` scaled with the item. */\nconst limit = (value: number | undefined, factor: number) =>\n value === undefined ? undefined : Math.max(1, Math.round(value * factor))\n\n/**\n * The layout worked out for a grid of another width: positions and widths\n * scaled by the ratio of the columns, then settled. Items in a row that\n * were equally wide stay equally wide, by wrapping the row or leaving\n * columns empty (see the docs). On a single column the items are stacked\n * in reading order (top to bottom, then left to right), each keeping its height.\n */\nexport function deriveLayout(\n items: readonly GridItem[],\n from: number,\n options: GridLayoutOptions,\n): readonly GridItem[] {\n const to = options.columns\n if (from === to) return normalizeLayout(items, options)\n if (to === 1) {\n const order = items.map((_, i) => i)\n order.sort((a, b) => items[a]!.y - items[b]!.y || items[a]!.x - items[b]!.x || a - b)\n const out = items.slice()\n let y = 0\n for (const i of order) {\n const item = fitItem({ ...items[i]!, x: 0, w: 1 }, 1)\n out[i] = { ...item, y }\n y += item.h\n }\n return out\n }\n const rows = new Map<number, GridItem[]>()\n for (const item of items) {\n const row = rows.get(item.y)\n if (row) row.push(item)\n else rows.set(item.y, [item])\n }\n const ys = [...rows.keys()]\n ys.sort((a, b) => a - b)\n const placed = new Map<GridItem, GridItem>()\n // lines a row wraps onto push everything below it down\n let shift = 0\n for (const y of ys) {\n const row = rows.get(y)!\n row.sort((a, b) => a.x - b.x)\n const h = row[0]!.h\n const band =\n row.every((item) => item.h === h) &&\n items.every((item) => item.y === y || item.y + item.h <= y || item.y >= y + h)\n const spans = scaleRow(row, band, from, to)\n for (const span of spans)\n placed.set(\n span.item,\n fitItem(\n {\n ...span.item,\n x: span.x,\n y: y + shift + span.line * h,\n w: span.w,\n minW: limit(span.item.minW, span.factor),\n maxW: limit(span.item.maxW, span.factor),\n },\n to,\n ),\n )\n shift += spans[spans.length - 1]!.line * h\n }\n return normalizeLayout(\n items.map((item) => placed.get(item)!),\n options,\n )\n}\n"],"mappings":"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"}
package/dist/style.js CHANGED
@@ -4,9 +4,15 @@ import 'dou-ui/components/dialog/style'
4
4
  import 'dou-ui/components/drawer/style'
5
5
  import 'dou-ui/components/editable/style'
6
6
  import 'dou-ui/components/dropdown/style'
7
- import 'dou-ui/components/empty/style'
8
7
  import 'dou-ui/components/grid/style'
8
+ import 'dou-ui/components/input-number/style'
9
+ import 'dou-ui/components/segmented-control/style'
9
10
  import 'dou-ui/components/select/style'
11
+ import 'dou-ui/components/sparkline/style'
12
+ import 'dou-ui/components/statistic/style'
13
+ import 'dou-ui/components/switch/style'
14
+ import 'dou-ui/components/table/style'
15
+ import 'dou-ui/components/textarea/style'
10
16
  import 'dou-ui/components/tooltip/style'
11
17
  import '@dou-ui/sheet/style'
12
18
  import './style.css'
@@ -42,9 +42,10 @@ export declare function resizeItemBy(items: readonly GridItem[], id: string, dw:
42
42
  export declare function findPlace(items: readonly GridItem[], size: GridSize, options: GridLayoutOptions): GridPosition;
43
43
  /**
44
44
  * The layout worked out for a grid of another width: positions and widths
45
- * scaled by the ratio of the columns, then settled. On a single column the
46
- * items are stacked in reading order (top to bottom, then left to right),
47
- * each keeping its height.
45
+ * scaled by the ratio of the columns, then settled. Items in a row that
46
+ * were equally wide stay equally wide, by wrapping the row or leaving
47
+ * columns empty (see the docs). On a single column the items are stacked
48
+ * in reading order (top to bottom, then left to right), each keeping its height.
48
49
  */
49
50
  export declare function deriveLayout(items: readonly GridItem[], from: number, options: GridLayoutOptions): readonly GridItem[];
50
51
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dou-ui/dashboard",
3
- "version": "0.1.0-alpha.0",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "DouUI 的仪表盘:可拖动、可缩放的网格布局与仪表盘设计器",
5
5
  "keywords": [
6
6
  "vue",
@@ -67,9 +67,9 @@
67
67
  "build": "vite build && vue-tsc -p tsconfig.build.json && bun scripts/build-style.ts"
68
68
  },
69
69
  "peerDependencies": {
70
- "@dou-ui/chart": "0.1.0-alpha.0",
71
- "@dou-ui/pivot": "0.1.0-alpha.0",
72
- "dou-ui": "0.1.0-alpha.0",
70
+ "@dou-ui/chart": "0.1.0-alpha.2",
71
+ "@dou-ui/pivot": "0.1.0-alpha.2",
72
+ "dou-ui": "0.1.0-alpha.2",
73
73
  "vue": "^3.5.0",
74
74
  "yjs": "^13.6.0"
75
75
  },
@@ -85,12 +85,12 @@
85
85
  }
86
86
  },
87
87
  "dependencies": {
88
- "@dou-ui/icons": "0.1.0-alpha.0",
89
- "@dou-ui/sheet": "0.1.0-alpha.0"
88
+ "@dou-ui/icons": "0.1.0-alpha.2",
89
+ "@dou-ui/sheet": "0.1.0-alpha.2"
90
90
  },
91
91
  "devDependencies": {
92
- "@dou-ui/chart": "0.1.0-alpha.0",
93
- "@dou-ui/pivot": "0.1.0-alpha.0",
92
+ "@dou-ui/chart": "0.1.0-alpha.2",
93
+ "@dou-ui/pivot": "0.1.0-alpha.2",
94
94
  "y-protocols": "^1.0.7",
95
95
  "yjs": "^13.6.33"
96
96
  },