@allshift/ui 0.5.0 → 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,12 +1065,19 @@ 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);
1057
1073
  boardRef.current = w;
1058
1074
  boardHRef.current = Math.max(480, window.innerHeight);
1059
1075
  setBoardWidth(w);
1076
+ setBlocks((prev) => {
1077
+ const next = fitToBoard(prev, w, boardHRef.current);
1078
+ if (next !== prev) fitAdjustRef.current = true;
1079
+ return next;
1080
+ });
1060
1081
  };
1061
1082
  measure();
1062
1083
  window.addEventListener("resize", measure);
@@ -1297,7 +1318,10 @@ function CanvasProvider({
1297
1318
  restoredRef.current = true;
1298
1319
  setCanRestore(false);
1299
1320
  const built = saved.filter((b) => b && typeof b.key === "string" && resolve(b.key)).map((b) => blockFromSaved(b, zRef.current++));
1300
- 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);
1301
1325
  }, [savedSession, layoutDefault]);
1302
1326
  const clear = (0, import_react10.useCallback)((keepKey) => {
1303
1327
  setBlocks((prev) => keepKey ? prev.filter((b) => b.key === keepKey) : []);
@@ -1414,6 +1438,12 @@ function CanvasProvider({
1414
1438
  firstRun.current = false;
1415
1439
  return;
1416
1440
  }
1441
+ if (fitAdjustRef.current) {
1442
+ fitAdjustRef.current = false;
1443
+ if (!hadUserChangeRef.current) return;
1444
+ } else {
1445
+ hadUserChangeRef.current = true;
1446
+ }
1417
1447
  if (!payloadRef.current) return;
1418
1448
  if (saveTimer.current) clearTimeout(saveTimer.current);
1419
1449
  const body = JSON.stringify(payloadRef.current);
@@ -1432,6 +1462,7 @@ function CanvasProvider({
1432
1462
  (0, import_react10.useEffect)(() => {
1433
1463
  if (!persist) return;
1434
1464
  const flush = () => {
1465
+ if (!hadUserChangeRef.current) return;
1435
1466
  if (!payloadRef.current) return;
1436
1467
  try {
1437
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,12 +1025,19 @@ 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);
1017
1033
  boardRef.current = w;
1018
1034
  boardHRef.current = Math.max(480, window.innerHeight);
1019
1035
  setBoardWidth(w);
1036
+ setBlocks((prev) => {
1037
+ const next = fitToBoard(prev, w, boardHRef.current);
1038
+ if (next !== prev) fitAdjustRef.current = true;
1039
+ return next;
1040
+ });
1020
1041
  };
1021
1042
  measure();
1022
1043
  window.addEventListener("resize", measure);
@@ -1257,7 +1278,10 @@ function CanvasProvider({
1257
1278
  restoredRef.current = true;
1258
1279
  setCanRestore(false);
1259
1280
  const built = saved.filter((b) => b && typeof b.key === "string" && resolve(b.key)).map((b) => blockFromSaved(b, zRef.current++));
1260
- 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);
1261
1285
  }, [savedSession, layoutDefault]);
1262
1286
  const clear = useCallback((keepKey) => {
1263
1287
  setBlocks((prev) => keepKey ? prev.filter((b) => b.key === keepKey) : []);
@@ -1374,6 +1398,12 @@ function CanvasProvider({
1374
1398
  firstRun.current = false;
1375
1399
  return;
1376
1400
  }
1401
+ if (fitAdjustRef.current) {
1402
+ fitAdjustRef.current = false;
1403
+ if (!hadUserChangeRef.current) return;
1404
+ } else {
1405
+ hadUserChangeRef.current = true;
1406
+ }
1377
1407
  if (!payloadRef.current) return;
1378
1408
  if (saveTimer.current) clearTimeout(saveTimer.current);
1379
1409
  const body = JSON.stringify(payloadRef.current);
@@ -1392,6 +1422,7 @@ function CanvasProvider({
1392
1422
  useEffect6(() => {
1393
1423
  if (!persist) return;
1394
1424
  const flush = () => {
1425
+ if (!hadUserChangeRef.current) return;
1395
1426
  if (!payloadRef.current) return;
1396
1427
  try {
1397
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.0",
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,