@natsuneko-laboratory/react-native-desktop-navigation 0.1.0-alpha.12 → 0.1.0-alpha.14
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/native/host.js +31 -7
- package/package.json +1 -1
- package/src/native/host.tsx +38 -8
package/dist/native/host.js
CHANGED
|
@@ -92,17 +92,40 @@ function NativeSurface({ configuration, slots, icons = [], footer, onFooterHeigh
|
|
|
92
92
|
}
|
|
93
93
|
const [acknowledgement, acknowledge] = react_1.default.useReducer((n) => n + 1, 0);
|
|
94
94
|
const serialized = JSON.stringify(configuration);
|
|
95
|
-
|
|
95
|
+
// Selection and acknowledgements do not invalidate sidebar icon positions.
|
|
96
|
+
// Other configuration changes may move/resize rows, so await fresh geometry.
|
|
97
|
+
const iconLayoutConfiguration = JSON.stringify({
|
|
98
|
+
...configuration,
|
|
99
|
+
activeKey: undefined,
|
|
100
|
+
items: configuration.items.map((item) => ({
|
|
101
|
+
...item,
|
|
102
|
+
// Native icons occupy fixed square slots. Switching a symbol/glyph,
|
|
103
|
+
// image or tint on selection changes its contents, not row geometry.
|
|
104
|
+
icon: item.icon && { type: item.icon.type, size: item.icon.size },
|
|
105
|
+
})),
|
|
106
|
+
});
|
|
107
|
+
const version = react_1.default.useRef({
|
|
108
|
+
serialized,
|
|
109
|
+
acknowledgement,
|
|
110
|
+
revision: 0,
|
|
111
|
+
iconLayoutConfiguration,
|
|
112
|
+
iconLayoutRevision: 0,
|
|
113
|
+
});
|
|
96
114
|
if (version.current.serialized !== serialized ||
|
|
97
115
|
version.current.acknowledgement !== acknowledgement) {
|
|
98
116
|
version.current = {
|
|
99
117
|
serialized,
|
|
100
118
|
acknowledgement,
|
|
101
119
|
revision: version.current.revision + 1,
|
|
120
|
+
iconLayoutConfiguration,
|
|
121
|
+
iconLayoutRevision: version.current.iconLayoutRevision +
|
|
122
|
+
Number(version.current.iconLayoutConfiguration !== iconLayoutConfiguration),
|
|
102
123
|
};
|
|
103
124
|
}
|
|
104
125
|
const revision = version.current.revision;
|
|
105
|
-
const
|
|
126
|
+
const iconLayoutRevision = version.current.iconLayoutRevision;
|
|
127
|
+
const [measurement, setMeasurement] = react_1.default.useState(null);
|
|
128
|
+
const layout = measurement?.event;
|
|
106
129
|
const footerFrame = layout?.footerFrame;
|
|
107
130
|
const footerPlaced = !!footerFrame && footerFrame.width > 0;
|
|
108
131
|
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [styles.container, style], onLayout: onLayout, children: [(0, jsx_runtime_1.jsx)(DesktopNavigationHostNativeComponent_1.default, { style: react_native_1.StyleSheet.absoluteFillObject, configuration: JSON.stringify({ ...configuration, revision }), onNavigationEvent: (event) => {
|
|
@@ -111,9 +134,9 @@ function NativeSurface({ configuration, slots, icons = [], footer, onFooterHeigh
|
|
|
111
134
|
return;
|
|
112
135
|
if (message.type === 'layout') {
|
|
113
136
|
onMeasurements?.(message.frames);
|
|
114
|
-
|
|
137
|
+
setMeasurement((previous) => JSON.stringify(previous?.event) === JSON.stringify(message)
|
|
115
138
|
? previous
|
|
116
|
-
: message);
|
|
139
|
+
: { event: message, iconLayoutRevision });
|
|
117
140
|
}
|
|
118
141
|
else {
|
|
119
142
|
onRequest(message);
|
|
@@ -154,9 +177,10 @@ function NativeSurface({ configuration, slots, icons = [], footer, onFooterHeigh
|
|
|
154
177
|
opacity: 0,
|
|
155
178
|
},
|
|
156
179
|
], children: footer })), (0, jsx_runtime_1.jsx)(react_native_1.View, { pointerEvents: "none", accessible: false, accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", style: react_native_1.StyleSheet.absoluteFillObject, children: icons.map((icon) => {
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
180
|
+
// Keep SVGs mounted across selection-only revisions, but never reuse
|
|
181
|
+
// positions after a layout configuration change (even if reverted).
|
|
182
|
+
const geometry = measurement?.iconLayoutRevision === iconLayoutRevision
|
|
183
|
+
? layout?.iconFrames?.[icon.key]
|
|
160
184
|
: undefined;
|
|
161
185
|
if (!geometry ||
|
|
162
186
|
geometry.clip.width <= 0 ||
|
package/package.json
CHANGED
package/src/native/host.tsx
CHANGED
|
@@ -211,7 +211,25 @@ export function NativeSurface({
|
|
|
211
211
|
}
|
|
212
212
|
const [acknowledgement, acknowledge] = React.useReducer((n) => n + 1, 0);
|
|
213
213
|
const serialized = JSON.stringify(configuration);
|
|
214
|
-
|
|
214
|
+
// Selection and acknowledgements do not invalidate sidebar icon positions.
|
|
215
|
+
// Other configuration changes may move/resize rows, so await fresh geometry.
|
|
216
|
+
const iconLayoutConfiguration = JSON.stringify({
|
|
217
|
+
...configuration,
|
|
218
|
+
activeKey: undefined,
|
|
219
|
+
items: configuration.items.map((item) => ({
|
|
220
|
+
...item,
|
|
221
|
+
// Native icons occupy fixed square slots. Switching a symbol/glyph,
|
|
222
|
+
// image or tint on selection changes its contents, not row geometry.
|
|
223
|
+
icon: item.icon && { type: item.icon.type, size: item.icon.size },
|
|
224
|
+
})),
|
|
225
|
+
});
|
|
226
|
+
const version = React.useRef({
|
|
227
|
+
serialized,
|
|
228
|
+
acknowledgement,
|
|
229
|
+
revision: 0,
|
|
230
|
+
iconLayoutConfiguration,
|
|
231
|
+
iconLayoutRevision: 0,
|
|
232
|
+
});
|
|
215
233
|
if (
|
|
216
234
|
version.current.serialized !== serialized ||
|
|
217
235
|
version.current.acknowledgement !== acknowledgement
|
|
@@ -220,10 +238,21 @@ export function NativeSurface({
|
|
|
220
238
|
serialized,
|
|
221
239
|
acknowledgement,
|
|
222
240
|
revision: version.current.revision + 1,
|
|
241
|
+
iconLayoutConfiguration,
|
|
242
|
+
iconLayoutRevision:
|
|
243
|
+
version.current.iconLayoutRevision +
|
|
244
|
+
Number(
|
|
245
|
+
version.current.iconLayoutConfiguration !== iconLayoutConfiguration,
|
|
246
|
+
),
|
|
223
247
|
};
|
|
224
248
|
}
|
|
225
249
|
const revision = version.current.revision;
|
|
226
|
-
const
|
|
250
|
+
const iconLayoutRevision = version.current.iconLayoutRevision;
|
|
251
|
+
const [measurement, setMeasurement] = React.useState<{
|
|
252
|
+
event: LayoutEvent;
|
|
253
|
+
iconLayoutRevision: number;
|
|
254
|
+
} | null>(null);
|
|
255
|
+
const layout = measurement?.event;
|
|
227
256
|
const footerFrame = layout?.footerFrame;
|
|
228
257
|
const footerPlaced = !!footerFrame && footerFrame.width > 0;
|
|
229
258
|
return (
|
|
@@ -236,10 +265,10 @@ export function NativeSurface({
|
|
|
236
265
|
if (!message || message.revision !== revision) return;
|
|
237
266
|
if (message.type === 'layout') {
|
|
238
267
|
onMeasurements?.(message.frames);
|
|
239
|
-
|
|
240
|
-
JSON.stringify(previous) === JSON.stringify(message)
|
|
268
|
+
setMeasurement((previous) =>
|
|
269
|
+
JSON.stringify(previous?.event) === JSON.stringify(message)
|
|
241
270
|
? previous
|
|
242
|
-
: message,
|
|
271
|
+
: { event: message, iconLayoutRevision },
|
|
243
272
|
);
|
|
244
273
|
} else {
|
|
245
274
|
onRequest(message);
|
|
@@ -321,10 +350,11 @@ export function NativeSurface({
|
|
|
321
350
|
style={StyleSheet.absoluteFillObject}
|
|
322
351
|
>
|
|
323
352
|
{icons.map((icon) => {
|
|
324
|
-
//
|
|
353
|
+
// Keep SVGs mounted across selection-only revisions, but never reuse
|
|
354
|
+
// positions after a layout configuration change (even if reverted).
|
|
325
355
|
const geometry =
|
|
326
|
-
|
|
327
|
-
? layout
|
|
356
|
+
measurement?.iconLayoutRevision === iconLayoutRevision
|
|
357
|
+
? layout?.iconFrames?.[icon.key]
|
|
328
358
|
: undefined;
|
|
329
359
|
if (
|
|
330
360
|
!geometry ||
|