@gjsify/example-dom-three-loader-ldraw 0.54.0 → 0.56.0

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.html CHANGED
@@ -4,7 +4,6 @@
4
4
  <meta charset="utf-8" />
5
5
  <title>LDraw Loader — gjsify</title>
6
6
  <link rel="stylesheet" href="./webgl.css" type="text/css" />
7
- <link rel="stylesheet" href="./browser.css" type="text/css" />
8
7
  <script src="./browser.js" type="module" defer></script>
9
8
  </head>
10
9
  <body></body>
package/dist/webgl.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /* Page chrome for the STANDALONE `index.html` only — how the window is centred
2
- on an otherwise empty page. The window's own layout (sidebar vs. GL area) is
3
- deliberately NOT here: `browser.ts` builds an <adw-overlay-split-view> and
2
+ on an otherwise empty page. The window's own layout (controls vs. GL area) is
3
+ deliberately NOT here: `browser.ts` mounts the `.blp` tree and
4
4
  inline-styles the GL container, because the website embeds `mount()` without
5
5
  ever loading this file, and a layout that lives here is a layout the embed
6
6
  does not get. */
@@ -21,7 +21,7 @@ html, body {
21
21
  justify-content: center;
22
22
  }
23
23
 
24
- adw-window {
24
+ adw-application-window {
25
25
  max-width: 100%;
26
26
  max-height: 100%;
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/example-dom-three-loader-ldraw",
3
- "version": "0.54.0",
3
+ "version": "0.56.0",
4
4
  "description": "Three.js LDraw loader showcase ported from refs/three/examples/webgl_loader_ldraw.html with Adwaita controls",
5
5
  "main": "dist/gjs.js",
6
6
  "type": "module",
@@ -28,7 +28,7 @@
28
28
  "build:assets": "gjsify copy src/browser/index.html src/browser/webgl.css src/assets dist/"
29
29
  },
30
30
  "dependencies": {
31
- "@gjsify/webgl": "^0.54.0"
31
+ "@gjsify/webgl": "^0.56.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@girs/adw-1": "5.4.0",
@@ -36,11 +36,11 @@
36
36
  "@girs/gjs": "5.4.0",
37
37
  "@girs/gobject-2.0": "5.4.0",
38
38
  "@girs/gtk-4.0": "5.4.0",
39
- "@gjsify/adwaita-web": "^0.54.0",
40
- "@gjsify/cli": "^0.54.0",
41
- "@gjsify/devtools": "^0.54.0",
39
+ "@gjsify/adwaita-web": "^0.56.0",
40
+ "@gjsify/cli": "^0.56.0",
41
+ "@gjsify/devtools": "^0.56.0",
42
42
  "@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
43
- "@gjsify/vite-plugin-blueprint": "^0.54.0",
43
+ "@gjsify/vite-plugin-blueprint": "^0.56.0",
44
44
  "@types/node": "^25.9.2",
45
45
  "@types/three": "^0.185.0",
46
46
  "http-server": "^14.1.1",
@@ -1,5 +1,7 @@
1
1
  // Browser UI for three-loader-ldraw example.
2
- // Mirrors the GJS/Adwaita UI using @gjsify/adwaita-web.
2
+ // The widget tree is the GJS window's own `ldraw-window.blp`, projected and mounted by
3
+ // @gjsify/adwaita-web — one authored file, so the control groups and the GL area cannot drift
4
+ // from the GTK build.
3
5
  // Ported from refs/three/examples/webgl_loader_ldraw.html
4
6
  // Original: MIT license, three.js authors (https://threejs.org)
5
7
  // This software uses the LDraw Parts Library (http://www.ldraw.org), CC BY 2.0.
@@ -9,14 +11,14 @@
9
11
  // dead twice over: under this build css-as-string turns it into a string a
10
12
  // side-effect import discards, and under a real CSS pipeline it injects the same
11
13
  // rules a SECOND time (`style.css.d.ts` says so).
12
- import '@gjsify/adwaita-web';
14
+ import { mountSharedTree } from '@gjsify/adwaita-web';
13
15
  // A showcase is served to whatever browser opens it, so it cannot assume the host has
14
16
  // Adwaita Sans the way a GNOME desktop does. `import '@gjsify/adwaita-web'` names the
15
17
  // family and ships no `@font-face`, so without this call the chrome renders in the host's
16
18
  // default sans on macOS, on Windows and on any Linux that is not GNOME — and looks right
17
19
  // only on the machine it was written on.
18
20
  import { applyAdwaitaFonts } from '@gjsify/adwaita-web/fonts';
19
- import type { Adw } from '@gjsify/adwaita-web';
21
+ import tree from '../gjs/ldraw-window.blp?shared-tree';
20
22
  import { start, MODEL_LIST, DEFAULT_MODEL_INDEX, type LDrawDemo } from '../three-demo.js';
21
23
 
22
24
  // Idempotent, and a no-op where there is no `document` — so a build-time import of this
@@ -38,84 +40,50 @@ export interface ShowcaseHandle {
38
40
  readonly isPaused: boolean;
39
41
  }
40
42
 
43
+ /** The one element of the mounted tree with this authored id. */
44
+ function byId(root: HTMLElement, id: string): HTMLElement {
45
+ const el = root.querySelector<HTMLElement>(`#${id}`);
46
+ if (el === null) throw new Error(`ldraw-window.blp declares no object with the id "${id}"`);
47
+ return el;
48
+ }
49
+
50
+ /**
51
+ * The values `ldraw-window.ts` sets in TypeScript because Blueprint has no spelling for them
52
+ * here, so they are not in the tree and this is the browser's copy. Keep the two in step.
53
+ *
54
+ * | id | attribute | value | GTK counterpart |
55
+ * | ------------------ | ------------ | --------------------------------------- | --------------------------------------------- |
56
+ * | `modelRow` | `model` | `MODEL_LIST` names | `set_model(Gtk.StringList.new(…))` |
57
+ * | `modelRow` | `selected` | `DEFAULT_MODEL_INDEX` | `set_selected(DEFAULT_MODEL_INDEX)` |
58
+ * | `buildingStepRow` | `adjustment` | `lower 0, upper 0, stepIncrement 1, value 0` | `set_adjustment(new Gtk.Adjustment(…))` |
59
+ *
60
+ * `upper` and `value` of the building step follow the loaded model (see the `start` callback).
61
+ */
62
+ const TS_ONLY = {
63
+ modelRow: { model: MODEL_LIST.map((m) => m.name), selected: DEFAULT_MODEL_INDEX },
64
+ buildingStepRow: { lower: 0, upper: 0, stepIncrement: 1, value: 0 },
65
+ };
66
+
41
67
  export function mount(container: HTMLElement, options?: MountOptions): ShowcaseHandle {
42
68
  const { assetBase } = options ?? {};
43
69
 
44
- const win = document.createElement('adw-window');
45
- win.setAttribute('width', '1100');
46
- win.setAttribute('height', '700');
70
+ const { root: win } = mountSharedTree(tree, { into: container });
71
+
72
+ const modelRow = byId(win, 'modelRow');
73
+ const flatColorsRow = byId(win, 'flatColorsRow');
74
+ const mergeModelRow = byId(win, 'mergeModelRow');
75
+ const smoothNormalsRow = byId(win, 'smoothNormalsRow');
76
+ const buildingStepRow = byId(win, 'buildingStepRow');
77
+ const displayLinesRow = byId(win, 'displayLinesRow');
78
+ const conditionalLinesRow = byId(win, 'conditionalLinesRow');
47
79
 
48
- const headerBar = document.createElement('adw-header-bar');
49
- headerBar.setAttribute('title', 'LDraw Loader');
80
+ modelRow.setAttribute('model', JSON.stringify(TS_ONLY.modelRow.model));
81
+ modelRow.setAttribute('selected', String(TS_ONLY.modelRow.selected));
82
+ buildingStepRow.setAttribute('adjustment', JSON.stringify(TS_ONLY.buildingStepRow));
50
83
 
51
84
  // A showcase has two hosts — the standalone page and the website embed — and only the former
52
85
  // loads `browser/webgl.css`, so the layout has to live here rather than in that stylesheet.
53
- const splitView = document.createElement('adw-overlay-split-view') as Adw.OverlaySplitView;
54
- splitView.setAttribute('min-sidebar-width', '280');
55
- splitView.setAttribute('max-sidebar-width', '400');
56
- splitView.setAttribute('sidebar-width-fraction', '0.30');
57
- splitView.setAttribute('show-sidebar', '');
58
-
59
- // Inline styles for the same reason as the GL container below.
60
- const sidebarContent = document.createElement('div');
61
- sidebarContent.setAttribute('slot', 'sidebar');
62
- sidebarContent.className = 'adw-sidebar-content';
63
- sidebarContent.style.cssText = 'padding:12px;display:flex;flex-direction:column;gap:12px';
64
-
65
- const modelGroup = document.createElement('adw-preferences-group');
66
- modelGroup.setAttribute('title', 'Model');
67
-
68
- const modelRow = document.createElement('adw-combo-row');
69
- modelRow.setAttribute('title', 'Model');
70
- modelRow.setAttribute('items', JSON.stringify(MODEL_LIST.map((m) => m.name)));
71
- modelRow.setAttribute('selected', String(DEFAULT_MODEL_INDEX));
72
-
73
- modelGroup.append(modelRow);
74
-
75
- // Rendering group
76
- const renderGroup = document.createElement('adw-preferences-group');
77
- renderGroup.setAttribute('title', 'Rendering');
78
-
79
- const flatColorsRow = document.createElement('adw-switch-row');
80
- flatColorsRow.setAttribute('title', 'Flat Colors');
81
-
82
- const mergeModelRow = document.createElement('adw-switch-row');
83
- mergeModelRow.setAttribute('title', 'Merge Model');
84
-
85
- const smoothNormalsRow = document.createElement('adw-switch-row');
86
- smoothNormalsRow.setAttribute('title', 'Smooth Normals');
87
- smoothNormalsRow.setAttribute('active', '');
88
-
89
- renderGroup.append(flatColorsRow, mergeModelRow, smoothNormalsRow);
90
-
91
- // Display group
92
- const displayGroup = document.createElement('adw-preferences-group');
93
- displayGroup.setAttribute('title', 'Display');
94
-
95
- const buildingStepRow = document.createElement('adw-spin-row');
96
- buildingStepRow.setAttribute('title', 'Building Step');
97
- buildingStepRow.setAttribute('min', '0');
98
- buildingStepRow.setAttribute('max', '0');
99
- buildingStepRow.setAttribute('step', '1');
100
- buildingStepRow.setAttribute('value', '0');
101
-
102
- const displayLinesRow = document.createElement('adw-switch-row');
103
- displayLinesRow.setAttribute('title', 'Display Lines');
104
- displayLinesRow.setAttribute('active', '');
105
-
106
- const conditionalLinesRow = document.createElement('adw-switch-row');
107
- conditionalLinesRow.setAttribute('title', 'Conditional Lines');
108
- conditionalLinesRow.setAttribute('active', '');
109
-
110
- displayGroup.append(buildingStepRow, displayLinesRow, conditionalLinesRow);
111
-
112
- sidebarContent.append(modelGroup, renderGroup, displayGroup);
113
-
114
- // GL container (content slot) — inline styles so the showcase
115
- // is self-contained and works regardless of host CSS.
116
- const glContainer = document.createElement('div');
117
- glContainer.setAttribute('slot', 'content');
118
- glContainer.id = 'gl-area-container';
86
+ const glContainer = byId(win, 'glAreaContainer');
119
87
  glContainer.style.cssText = 'flex:1;position:relative;min-width:0;min-height:0';
120
88
 
121
89
  const canvas = document.createElement('canvas');
@@ -123,10 +91,6 @@ export function mount(container: HTMLElement, options?: MountOptions): ShowcaseH
123
91
  canvas.style.cssText = 'display:block;width:100%;height:100%;position:absolute;inset:0';
124
92
  glContainer.append(canvas);
125
93
 
126
- splitView.append(sidebarContent, glContainer);
127
- win.append(headerBar, splitView);
128
- container.append(win);
129
-
130
94
  // Sync canvas size
131
95
  new ResizeObserver(() => {
132
96
  canvas.width = glContainer.clientWidth;
@@ -138,9 +102,10 @@ export function mount(container: HTMLElement, options?: MountOptions): ShowcaseH
138
102
  // Start three.js
139
103
  const demo = start(canvas, { assetBase }, (numSteps) => {
140
104
  // Update building step range when model loads
141
- buildingStepRow.setAttribute('max', String(numSteps - 1));
142
- // oxlint-disable-next-line typescript/no-explicit-any -- adw-spin-row is a custom element with no TypeScript type for .value property
143
- (buildingStepRow as any).value = numSteps - 1;
105
+ buildingStepRow.setAttribute(
106
+ 'adjustment',
107
+ JSON.stringify({ ...TS_ONLY.buildingStepRow, upper: numSteps - 1, value: numSteps - 1 }),
108
+ );
144
109
  });
145
110
 
146
111
  connectControls(
@@ -4,7 +4,6 @@
4
4
  <meta charset="utf-8" />
5
5
  <title>LDraw Loader — gjsify</title>
6
6
  <link rel="stylesheet" href="./webgl.css" type="text/css" />
7
- <link rel="stylesheet" href="./browser.css" type="text/css" />
8
7
  <script src="./browser.js" type="module" defer></script>
9
8
  </head>
10
9
  <body></body>
@@ -1,6 +1,6 @@
1
1
  /* Page chrome for the STANDALONE `index.html` only — how the window is centred
2
- on an otherwise empty page. The window's own layout (sidebar vs. GL area) is
3
- deliberately NOT here: `browser.ts` builds an <adw-overlay-split-view> and
2
+ on an otherwise empty page. The window's own layout (controls vs. GL area) is
3
+ deliberately NOT here: `browser.ts` mounts the `.blp` tree and
4
4
  inline-styles the GL container, because the website embeds `mount()` without
5
5
  ever loading this file, and a layout that lives here is a layout the embed
6
6
  does not get. */
@@ -21,7 +21,7 @@ html, body {
21
21
  justify-content: center;
22
22
  }
23
23
 
24
- adw-window {
24
+ adw-application-window {
25
25
  max-width: 100%;
26
26
  max-height: 100%;
27
27
  }