@allshift/ui 0.5.1 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -1004,6 +1004,20 @@ function tileItems(items, boardW, boardH) {
1004
1004
  return { ...it, x, y, w, h: rowH };
1005
1005
  });
1006
1006
  }
1007
+ function fitToBoard(list, boardW, boardH) {
1008
+ if (list.length === 0) return list;
1009
+ const extent = Math.max(...list.map((b) => b.x + b.w));
1010
+ if (extent > boardW * 1.5) return tileItems(list, boardW, boardH);
1011
+ let changed = false;
1012
+ const next = list.map((b) => {
1013
+ const w = Math.min(b.w, boardW);
1014
+ const x = Math.max(0, Math.min(b.x, boardW - w));
1015
+ if (w === b.w && x === b.x) return b;
1016
+ changed = true;
1017
+ return { ...b, w, x };
1018
+ });
1019
+ return changed ? next : list;
1020
+ }
1007
1021
  function overlaps(a, b) {
1008
1022
  return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
1009
1023
  }
@@ -1051,6 +1065,8 @@ function CanvasProvider({
1051
1065
  (0, import_react10.useEffect)(() => {
1052
1066
  persistRef.current = persist;
1053
1067
  }, [persist]);
1068
+ const fitAdjustRef = (0, import_react10.useRef)(false);
1069
+ const hadUserChangeRef = (0, import_react10.useRef)(false);
1054
1070
  (0, import_react10.useEffect)(() => {
1055
1071
  const measure = () => {
1056
1072
  const w = Math.max(360, window.innerWidth - 40);
@@ -1058,15 +1074,9 @@ function CanvasProvider({
1058
1074
  boardHRef.current = Math.max(480, window.innerHeight);
1059
1075
  setBoardWidth(w);
1060
1076
  setBlocks((prev) => {
1061
- let changed = false;
1062
- const next = prev.map((b) => {
1063
- const bw = Math.min(b.w, w);
1064
- const bx = Math.max(0, Math.min(b.x, w - bw));
1065
- if (bw === b.w && bx === b.x) return b;
1066
- changed = true;
1067
- return { ...b, w: bw, x: bx };
1068
- });
1069
- return changed ? next : prev;
1077
+ const next = fitToBoard(prev, w, boardHRef.current);
1078
+ if (next !== prev) fitAdjustRef.current = true;
1079
+ return next;
1070
1080
  });
1071
1081
  };
1072
1082
  measure();
@@ -1308,7 +1318,10 @@ function CanvasProvider({
1308
1318
  restoredRef.current = true;
1309
1319
  setCanRestore(false);
1310
1320
  const built = saved.filter((b) => b && typeof b.key === "string" && resolve(b.key)).map((b) => blockFromSaved(b, zRef.current++));
1311
- setBlocks(built.some((b) => b.placed) ? built : layoutDefault(built));
1321
+ const arranged = built.some((b) => b.placed) ? built : layoutDefault(built);
1322
+ const fitted = fitToBoard(arranged, boardRef.current, boardHRef.current);
1323
+ if (fitted !== arranged) fitAdjustRef.current = true;
1324
+ setBlocks(fitted);
1312
1325
  }, [savedSession, layoutDefault]);
1313
1326
  const clear = (0, import_react10.useCallback)((keepKey) => {
1314
1327
  setBlocks((prev) => keepKey ? prev.filter((b) => b.key === keepKey) : []);
@@ -1425,6 +1438,12 @@ function CanvasProvider({
1425
1438
  firstRun.current = false;
1426
1439
  return;
1427
1440
  }
1441
+ if (fitAdjustRef.current) {
1442
+ fitAdjustRef.current = false;
1443
+ if (!hadUserChangeRef.current) return;
1444
+ } else {
1445
+ hadUserChangeRef.current = true;
1446
+ }
1428
1447
  if (!payloadRef.current) return;
1429
1448
  if (saveTimer.current) clearTimeout(saveTimer.current);
1430
1449
  const body = JSON.stringify(payloadRef.current);
@@ -1443,6 +1462,7 @@ function CanvasProvider({
1443
1462
  (0, import_react10.useEffect)(() => {
1444
1463
  if (!persist) return;
1445
1464
  const flush = () => {
1465
+ if (!hadUserChangeRef.current) return;
1446
1466
  if (!payloadRef.current) return;
1447
1467
  try {
1448
1468
  void fetch("/api/canvas-layout", {
package/dist/index.js CHANGED
@@ -964,6 +964,20 @@ function tileItems(items, boardW, boardH) {
964
964
  return { ...it, x, y, w, h: rowH };
965
965
  });
966
966
  }
967
+ function fitToBoard(list, boardW, boardH) {
968
+ if (list.length === 0) return list;
969
+ const extent = Math.max(...list.map((b) => b.x + b.w));
970
+ if (extent > boardW * 1.5) return tileItems(list, boardW, boardH);
971
+ let changed = false;
972
+ const next = list.map((b) => {
973
+ const w = Math.min(b.w, boardW);
974
+ const x = Math.max(0, Math.min(b.x, boardW - w));
975
+ if (w === b.w && x === b.x) return b;
976
+ changed = true;
977
+ return { ...b, w, x };
978
+ });
979
+ return changed ? next : list;
980
+ }
967
981
  function overlaps(a, b) {
968
982
  return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
969
983
  }
@@ -1011,6 +1025,8 @@ function CanvasProvider({
1011
1025
  useEffect6(() => {
1012
1026
  persistRef.current = persist;
1013
1027
  }, [persist]);
1028
+ const fitAdjustRef = useRef6(false);
1029
+ const hadUserChangeRef = useRef6(false);
1014
1030
  useEffect6(() => {
1015
1031
  const measure = () => {
1016
1032
  const w = Math.max(360, window.innerWidth - 40);
@@ -1018,15 +1034,9 @@ function CanvasProvider({
1018
1034
  boardHRef.current = Math.max(480, window.innerHeight);
1019
1035
  setBoardWidth(w);
1020
1036
  setBlocks((prev) => {
1021
- let changed = false;
1022
- const next = prev.map((b) => {
1023
- const bw = Math.min(b.w, w);
1024
- const bx = Math.max(0, Math.min(b.x, w - bw));
1025
- if (bw === b.w && bx === b.x) return b;
1026
- changed = true;
1027
- return { ...b, w: bw, x: bx };
1028
- });
1029
- return changed ? next : prev;
1037
+ const next = fitToBoard(prev, w, boardHRef.current);
1038
+ if (next !== prev) fitAdjustRef.current = true;
1039
+ return next;
1030
1040
  });
1031
1041
  };
1032
1042
  measure();
@@ -1268,7 +1278,10 @@ function CanvasProvider({
1268
1278
  restoredRef.current = true;
1269
1279
  setCanRestore(false);
1270
1280
  const built = saved.filter((b) => b && typeof b.key === "string" && resolve(b.key)).map((b) => blockFromSaved(b, zRef.current++));
1271
- setBlocks(built.some((b) => b.placed) ? built : layoutDefault(built));
1281
+ const arranged = built.some((b) => b.placed) ? built : layoutDefault(built);
1282
+ const fitted = fitToBoard(arranged, boardRef.current, boardHRef.current);
1283
+ if (fitted !== arranged) fitAdjustRef.current = true;
1284
+ setBlocks(fitted);
1272
1285
  }, [savedSession, layoutDefault]);
1273
1286
  const clear = useCallback((keepKey) => {
1274
1287
  setBlocks((prev) => keepKey ? prev.filter((b) => b.key === keepKey) : []);
@@ -1385,6 +1398,12 @@ function CanvasProvider({
1385
1398
  firstRun.current = false;
1386
1399
  return;
1387
1400
  }
1401
+ if (fitAdjustRef.current) {
1402
+ fitAdjustRef.current = false;
1403
+ if (!hadUserChangeRef.current) return;
1404
+ } else {
1405
+ hadUserChangeRef.current = true;
1406
+ }
1388
1407
  if (!payloadRef.current) return;
1389
1408
  if (saveTimer.current) clearTimeout(saveTimer.current);
1390
1409
  const body = JSON.stringify(payloadRef.current);
@@ -1403,6 +1422,7 @@ function CanvasProvider({
1403
1422
  useEffect6(() => {
1404
1423
  if (!persist) return;
1405
1424
  const flush = () => {
1425
+ if (!hadUserChangeRef.current) return;
1406
1426
  if (!payloadRef.current) return;
1407
1427
  try {
1408
1428
  void fetch("/api/canvas-layout", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allshift/ui",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Shift family shared FEEL layer — glass morphism, 3D tilt physics, holographic shine, scroll-triggered generation, and the living-canvas engine (LiveCard, LiveStat, CanvasTransition, CanvasLauncher). Brand-neutral by design.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,