@things-factory/board-ui 10.1.268 → 10.1.270

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.
@@ -2,19 +2,28 @@ type ThumbnailScene = {
2
2
  root?: {
3
3
  model?: {
4
4
  threed?: boolean;
5
+ width?: number;
6
+ height?: number;
5
7
  };
6
8
  snapshot3d?: (width?: number, height?: number, type?: string, quality?: number, options?: {
7
9
  pose?: 'current' | 'start';
8
10
  }) => Promise<string | undefined>;
9
11
  };
12
+ toDataURL?: (type?: string, quality?: number, width?: number, height?: number) => Promise<unknown>;
10
13
  };
14
+ /** The board's own aspect inside 400x300, as board-service sizes the 2D one it renders - so a 3D tile fills like a 2D one. */
15
+ export declare function thumbnailSize(model?: {
16
+ width?: number;
17
+ height?: number;
18
+ }): [number, number];
11
19
  /**
12
- * The thumbnail the modeller sends with a save, or undefined to leave it to board-service.
20
+ * The thumbnail the modeller sends with a save: the board as it opens, so the list shows it the moment the save lands.
13
21
  *
14
- * A board that opens in 2D goes without one: board-service draws it headless, the same picture whoever saves. A board
15
- * that opens in 3D is taken here, from the 3D view at the camera 3D starts with (things-scene `snapshot3d`, pose
16
- * 'start'), whatever the person turned the camera to. When there is no 3D view to take - the modeller is showing 2D -
17
- * or the picture fails, the save goes without one and board-service draws it.
22
+ * A board that opens in 2D is the whole board drawn again at fit (things-scene `toDataURL`), without the modeller's
23
+ * zoom and pan. A board that opens in 3D is taken from the 3D view at the camera 3D starts with (`snapshot3d`, pose
24
+ * 'start'), whatever the person turned the camera to. Both come at the board's aspect inside 400x300, the size
25
+ * board-service renders one at. When there is no picture to take - a board that opens in 3D while the modeller shows
26
+ * 2D has no 3D view - or the picture fails, the save goes without one and board-service draws it.
18
27
  */
19
28
  export declare function startViewThumbnail(scene?: ThumbnailScene | null): Promise<string | undefined>;
20
29
  export {};
@@ -1,20 +1,33 @@
1
1
  /* the size board-service gives a thumbnail it renders, so tiles look alike whichever made them */
2
2
  const THUMBNAIL_WIDTH = 400;
3
3
  const THUMBNAIL_HEIGHT = 300;
4
+ /** The board's own aspect inside 400x300, as board-service sizes the 2D one it renders - so a 3D tile fills like a 2D one. */
5
+ export function thumbnailSize(model) {
6
+ const width = Number(model?.width) || 0;
7
+ const height = Number(model?.height) || 0;
8
+ if (!(width > 0) || !(height > 0))
9
+ return [THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT];
10
+ const ratio = Math.min(THUMBNAIL_WIDTH / width, THUMBNAIL_HEIGHT / height);
11
+ return [Math.floor(width * ratio), Math.floor(height * ratio)];
12
+ }
4
13
  /**
5
- * The thumbnail the modeller sends with a save, or undefined to leave it to board-service.
14
+ * The thumbnail the modeller sends with a save: the board as it opens, so the list shows it the moment the save lands.
6
15
  *
7
- * A board that opens in 2D goes without one: board-service draws it headless, the same picture whoever saves. A board
8
- * that opens in 3D is taken here, from the 3D view at the camera 3D starts with (things-scene `snapshot3d`, pose
9
- * 'start'), whatever the person turned the camera to. When there is no 3D view to take - the modeller is showing 2D -
10
- * or the picture fails, the save goes without one and board-service draws it.
16
+ * A board that opens in 2D is the whole board drawn again at fit (things-scene `toDataURL`), without the modeller's
17
+ * zoom and pan. A board that opens in 3D is taken from the 3D view at the camera 3D starts with (`snapshot3d`, pose
18
+ * 'start'), whatever the person turned the camera to. Both come at the board's aspect inside 400x300, the size
19
+ * board-service renders one at. When there is no picture to take - a board that opens in 3D while the modeller shows
20
+ * 2D has no 3D view - or the picture fails, the save goes without one and board-service draws it.
11
21
  */
12
22
  export async function startViewThumbnail(scene) {
13
23
  const root = scene?.root;
14
- if (!root?.model?.threed || !root.snapshot3d)
24
+ if (!scene || !root)
15
25
  return;
16
26
  try {
17
- const url = await root.snapshot3d(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, 'image/png', undefined, { pose: 'start' });
27
+ const [width, height] = thumbnailSize(root.model);
28
+ const url = root.model?.threed
29
+ ? await root.snapshot3d?.(width, height, 'image/png', undefined, { pose: 'start' })
30
+ : await scene.toDataURL?.('image/png', undefined, width, height);
18
31
  return typeof url === 'string' && url.startsWith('data:image/') ? url : undefined;
19
32
  }
20
33
  catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"board-thumbnail.js","sourceRoot":"","sources":["../../client/utils/board-thumbnail.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAe5B;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA6B;IACpE,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,CAAA;IACxB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAM;IAEpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QAC/G,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,6CAA8C,CAAW,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC,CAAA;QACvF,OAAM;IACR,CAAC;AACH,CAAC","sourcesContent":["/* the size board-service gives a thumbnail it renders, so tiles look alike whichever made them */\nconst THUMBNAIL_WIDTH = 400\nconst THUMBNAIL_HEIGHT = 300\n\ntype ThumbnailScene = {\n root?: {\n model?: { threed?: boolean }\n snapshot3d?: (\n width?: number,\n height?: number,\n type?: string,\n quality?: number,\n options?: { pose?: 'current' | 'start' }\n ) => Promise<string | undefined>\n }\n}\n\n/**\n * The thumbnail the modeller sends with a save, or undefined to leave it to board-service.\n *\n * A board that opens in 2D goes without one: board-service draws it headless, the same picture whoever saves. A board\n * that opens in 3D is taken here, from the 3D view at the camera 3D starts with (things-scene `snapshot3d`, pose\n * 'start'), whatever the person turned the camera to. When there is no 3D view to take - the modeller is showing 2D -\n * or the picture fails, the save goes without one and board-service draws it.\n */\nexport async function startViewThumbnail(scene?: ThumbnailScene | null): Promise<string | undefined> {\n const root = scene?.root\n if (!root?.model?.threed || !root.snapshot3d) return\n\n try {\n const url = await root.snapshot3d(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, 'image/png', undefined, { pose: 'start' })\n return typeof url === 'string' && url.startsWith('data:image/') ? url : undefined\n } catch (e) {\n console.warn(`[thumbnail] could not take the picture -- ${(e as Error)?.message ?? e}`)\n return\n }\n}\n"]}
1
+ {"version":3,"file":"board-thumbnail.js","sourceRoot":"","sources":["../../client/utils/board-thumbnail.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,MAAM,eAAe,GAAG,GAAG,CAAA;AAC3B,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAgB5B,8HAA8H;AAC9H,MAAM,UAAU,aAAa,CAAC,KAA2C;IACvE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;IACzC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAAE,OAAO,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAA;IAE7E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,GAAG,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAAC,CAAA;IAC1E,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAA;AAChE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,KAA6B;IACpE,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,CAAA;IACxB,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAM;IAE3B,IAAI,CAAC;QACH,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM;YAC5B,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YACnF,CAAC,CAAC,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAClE,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;IACnF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,6CAA8C,CAAW,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC,CAAA;QACvF,OAAM;IACR,CAAC;AACH,CAAC","sourcesContent":["/* the size board-service gives a thumbnail it renders, so tiles look alike whichever made them */\nconst THUMBNAIL_WIDTH = 400\nconst THUMBNAIL_HEIGHT = 300\n\ntype ThumbnailScene = {\n root?: {\n model?: { threed?: boolean; width?: number; height?: number }\n snapshot3d?: (\n width?: number,\n height?: number,\n type?: string,\n quality?: number,\n options?: { pose?: 'current' | 'start' }\n ) => Promise<string | undefined>\n }\n toDataURL?: (type?: string, quality?: number, width?: number, height?: number) => Promise<unknown>\n}\n\n/** The board's own aspect inside 400x300, as board-service sizes the 2D one it renders - so a 3D tile fills like a 2D one. */\nexport function thumbnailSize(model?: { width?: number; height?: number }): [number, number] {\n const width = Number(model?.width) || 0\n const height = Number(model?.height) || 0\n if (!(width > 0) || !(height > 0)) return [THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT]\n\n const ratio = Math.min(THUMBNAIL_WIDTH / width, THUMBNAIL_HEIGHT / height)\n return [Math.floor(width * ratio), Math.floor(height * ratio)]\n}\n\n/**\n * The thumbnail the modeller sends with a save: the board as it opens, so the list shows it the moment the save lands.\n *\n * A board that opens in 2D is the whole board drawn again at fit (things-scene `toDataURL`), without the modeller's\n * zoom and pan. A board that opens in 3D is taken from the 3D view at the camera 3D starts with (`snapshot3d`, pose\n * 'start'), whatever the person turned the camera to. Both come at the board's aspect inside 400x300, the size\n * board-service renders one at. When there is no picture to take - a board that opens in 3D while the modeller shows\n * 2D has no 3D view - or the picture fails, the save goes without one and board-service draws it.\n */\nexport async function startViewThumbnail(scene?: ThumbnailScene | null): Promise<string | undefined> {\n const root = scene?.root\n if (!scene || !root) return\n\n try {\n const [width, height] = thumbnailSize(root.model)\n const url = root.model?.threed\n ? await root.snapshot3d?.(width, height, 'image/png', undefined, { pose: 'start' })\n : await scene.toDataURL?.('image/png', undefined, width, height)\n return typeof url === 'string' && url.startsWith('data:image/') ? url : undefined\n } catch (e) {\n console.warn(`[thumbnail] could not take the picture -- ${(e as Error)?.message ?? e}`)\n return\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/board-ui",
3
- "version": "10.1.268",
3
+ "version": "10.1.270",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -26,7 +26,7 @@
26
26
  "clean": "npm run clean:server && npm run clean:client"
27
27
  },
28
28
  "dependencies": {
29
- "@hatiolab/things-scene": "^10.1.112",
29
+ "@hatiolab/things-scene": "^10.1.113",
30
30
  "@material/web": "^2.0.0",
31
31
  "@operato/app": "^10.29.43",
32
32
  "@operato/attachment": "^10.29.43",
@@ -44,12 +44,12 @@
44
44
  "@operato/shell": "^10.29.69",
45
45
  "@operato/styles": "^10.29.70",
46
46
  "@operato/utils": "^10.29.43",
47
- "@things-factory/ai-assistant": "^10.1.267",
48
- "@things-factory/barcode-base": "^10.1.267",
49
- "@things-factory/board-ai": "^10.1.268",
50
- "@things-factory/fav-base": "^10.1.267",
51
- "@things-factory/setting-base": "^10.1.267",
47
+ "@things-factory/ai-assistant": "^10.1.270",
48
+ "@things-factory/barcode-base": "^10.1.270",
49
+ "@things-factory/board-ai": "^10.1.270",
50
+ "@things-factory/fav-base": "^10.1.270",
51
+ "@things-factory/setting-base": "^10.1.270",
52
52
  "@things-factory/utils": "^10.1.179"
53
53
  },
54
- "gitHead": "06f4885c968eb6bf5fa0fd0f3226eaa66e8f93b9"
54
+ "gitHead": "9fb23e57702302f1a6c6572d9f0f37ef6f12b446"
55
55
  }
@@ -615,7 +615,7 @@
615
615
  "label.warning": "경고",
616
616
  "label.warnings": "경고",
617
617
  "label.wheel-size": "휠 크기",
618
- "label.width": "넓이",
618
+ "label.width": "너비",
619
619
  "label.will-get-return": "리턴값 반영",
620
620
  "label.wing": "날개",
621
621
  "label.with-credentials": "with credentials",