@bstage-sdk/react 0.8.7 → 0.9.1

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
@@ -154,38 +154,55 @@ function registerTemplate(template) {
154
154
 
155
155
  // src/hooks/useNavigation.ts
156
156
  var import_react4 = require("react");
157
- function useNavigation() {
158
- const ctx = (0, import_react4.useContext)(BstageContext);
159
- const bridge = ctx?.bridge;
160
- const navigate = (0, import_react4.useCallback)(
161
- (path, params) => {
162
- if (bridge) {
163
- bridge.emit("navigate", { path, params });
157
+ var import_core2 = require("@bstage-sdk/core");
158
+
159
+ // src/hooks/navigationActions.ts
160
+ function withQuery(path, params) {
161
+ return path + (params ? "?" + new URLSearchParams(params).toString() : "");
162
+ }
163
+ function createNavigationActions(frameBridge, platformBridge) {
164
+ if (frameBridge) {
165
+ const send = (type, payload) => {
166
+ frameBridge.request(type, payload).catch(() => {
167
+ });
168
+ };
169
+ return {
170
+ navigate: (path, params) => send("navigate", { path: withQuery(path, params) }),
171
+ goBack: () => send("back", {}),
172
+ openExternal: (url) => send("openExternal", { url })
173
+ };
174
+ }
175
+ return {
176
+ navigate: (path, params) => {
177
+ if (platformBridge) {
178
+ platformBridge.emit("navigate", { path, params });
164
179
  } else {
165
- const query = params ? "?" + new URLSearchParams(params).toString() : "";
166
- window.location.href = path + query;
180
+ window.location.href = withQuery(path, params);
167
181
  }
168
182
  },
169
- [bridge]
170
- );
171
- const goBack = (0, import_react4.useCallback)(() => {
172
- if (bridge) {
173
- bridge.emit("go-back", {});
174
- } else {
175
- window.history.back();
176
- }
177
- }, [bridge]);
178
- const openExternal = (0, import_react4.useCallback)(
179
- (url) => {
180
- if (bridge) {
181
- bridge.emit("open-external", { url });
183
+ goBack: () => {
184
+ if (platformBridge) {
185
+ platformBridge.emit("go-back", {});
182
186
  } else {
183
- window.open(url, "_blank");
187
+ window.history.back();
184
188
  }
185
189
  },
186
- [bridge]
187
- );
188
- return { navigate, goBack, openExternal };
190
+ openExternal: (url) => {
191
+ if (platformBridge) {
192
+ platformBridge.emit("open-external", { url });
193
+ } else {
194
+ window.open(url, "_blank");
195
+ }
196
+ }
197
+ };
198
+ }
199
+
200
+ // src/hooks/useNavigation.ts
201
+ function useNavigation() {
202
+ const ctx = (0, import_react4.useContext)(BstageContext);
203
+ const bridge = ctx?.bridge;
204
+ const frameBridge = (0, import_core2.getFrameBridge)();
205
+ return (0, import_react4.useMemo)(() => createNavigationActions(frameBridge, bridge), [frameBridge, bridge]);
189
206
  }
190
207
 
191
208
  // src/hooks/usePlatformEvent.ts
@@ -242,7 +259,7 @@ function hashString(str) {
242
259
 
243
260
  // src/hooks/useLocale.ts
244
261
  var import_react9 = require("react");
245
- var import_core2 = require("@bstage-sdk/core");
262
+ var import_core3 = require("@bstage-sdk/core");
246
263
 
247
264
  // src/LocaleProvider.tsx
248
265
  var import_react8 = require("react");
@@ -266,14 +283,14 @@ function BstageLocaleProvider({
266
283
  // src/hooks/useLocale.ts
267
284
  function useLocale() {
268
285
  const target = useLocaleTarget();
269
- const subscribe = (0, import_react9.useCallback)((onChange) => (0, import_core2.observeLocale)(onChange, target), [target]);
270
- const getSnapshot = (0, import_react9.useCallback)(() => (0, import_core2.readLocale)(target), [target]);
271
- const current = (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot, () => import_core2.DEFAULT_LANGUAGE);
286
+ const subscribe = (0, import_react9.useCallback)((onChange) => (0, import_core3.observeLocale)(onChange, target), [target]);
287
+ const getSnapshot = (0, import_react9.useCallback)(() => (0, import_core3.readLocale)(target), [target]);
288
+ const current = (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot, () => import_core3.DEFAULT_LANGUAGE);
272
289
  return { current };
273
290
  }
274
291
 
275
292
  // src/hooks/useMessages.ts
276
- var import_core3 = require("@bstage-sdk/core");
293
+ var import_core4 = require("@bstage-sdk/core");
277
294
 
278
295
  // src/devWarn.ts
279
296
  var warned = /* @__PURE__ */ new Set();
@@ -300,7 +317,7 @@ function useMessages(messages) {
300
317
  `useMessages\uC758 t('${String(key)}', ...) 2\uBC88\uC9F8 \uC778\uC790\uB294 \uBCF4\uAC04 \uD30C\uB77C\uBBF8\uD130 \uAC1D\uCCB4\uC785\uB2C8\uB2E4. fallback \uBB38\uC790\uC5F4\uC740 \uBB34\uC2DC\uB429\uB2C8\uB2E4.`
301
318
  );
302
319
  }
303
- const dict = messages[current] ?? messages[import_core3.DEFAULT_LANGUAGE] ?? Object.values(messages)[0] ?? {};
320
+ const dict = messages[current] ?? messages[import_core4.DEFAULT_LANGUAGE] ?? Object.values(messages)[0] ?? {};
304
321
  const template = dict[key] ?? key;
305
322
  return interpolate(template, params);
306
323
  };
@@ -308,7 +325,7 @@ function useMessages(messages) {
308
325
 
309
326
  // src/hooks/useBstageTranslations.ts
310
327
  var import_react10 = require("react");
311
- var import_core4 = require("@bstage-sdk/core");
328
+ var import_core5 = require("@bstage-sdk/core");
312
329
  var requiredDepth = /* @__PURE__ */ new Map();
313
330
  function useBstageTranslations() {
314
331
  const { current } = useLocale();
@@ -317,6 +334,8 @@ function useBstageTranslations() {
317
334
  const [dicts, setDicts] = (0, import_react10.useState)();
318
335
  const [depth, setDepth] = (0, import_react10.useState)(() => requiredDepth.get(depthKey) ?? 1);
319
336
  const pendingRef = (0, import_react10.useRef)(false);
337
+ const [translationsRevision, setTranslationsRevision] = (0, import_react10.useState)(0);
338
+ (0, import_react10.useEffect)(() => (0, import_core5.observeTranslations)(() => setTranslationsRevision((n) => n + 1)), []);
320
339
  (0, import_react10.useEffect)(() => {
321
340
  setDicts(void 0);
322
341
  setDepth(requiredDepth.get(depthKey) ?? 1);
@@ -324,8 +343,8 @@ function useBstageTranslations() {
324
343
  }, [depthKey]);
325
344
  (0, import_react10.useEffect)(() => {
326
345
  let active = true;
327
- const chain = (0, import_core4.resolveTranslationChain)(current).slice(0, depth);
328
- Promise.all(chain.map((locale) => (0, import_core4.fetchTranslations)(locale, target).catch(() => ({})))).then((loaded) => {
346
+ const chain = (0, import_core5.resolveTranslationChain)(current).slice(0, depth);
347
+ Promise.all(chain.map((locale) => (0, import_core5.fetchTranslations)(locale, target).catch(() => ({})))).then((loaded) => {
329
348
  if (!active) return;
330
349
  setDicts(loaded);
331
350
  pendingRef.current = false;
@@ -335,7 +354,7 @@ function useBstageTranslations() {
335
354
  return () => {
336
355
  active = false;
337
356
  };
338
- }, [current, target, depth]);
357
+ }, [current, target, depth, translationsRevision]);
339
358
  const requestFallback = (0, import_react10.useCallback)(
340
359
  (chainLength) => {
341
360
  if (pendingRef.current) return;
@@ -353,10 +372,10 @@ function useBstageTranslations() {
353
372
  );
354
373
  const resolveRaw = (0, import_react10.useCallback)(
355
374
  (key) => {
356
- const resolved = dicts ? (0, import_core4.pickTranslation)(dicts, key) : void 0;
375
+ const resolved = dicts ? (0, import_core5.pickTranslation)(dicts, key) : void 0;
357
376
  if (resolved !== void 0) return resolved;
358
377
  if (dicts) {
359
- const chain = (0, import_core4.resolveTranslationChain)(current);
378
+ const chain = (0, import_core5.resolveTranslationChain)(current);
360
379
  if (dicts.length < chain.length) {
361
380
  requestFallback(chain.length);
362
381
  } else if (process.env.NODE_ENV !== "production") {
@@ -387,14 +406,14 @@ function useBstageTranslations() {
387
406
  `'${String(key)}'\uB294 \uB9AC\uCE58\uD14D\uC2A4\uD2B8(<0>\u2026</0>) \uBB38\uAD6C\uC785\uB2C8\uB2E4. t()\uB294 \uBB38\uC790\uC5F4\uC744 \uBC18\uD658\uD558\uBBC0\uB85C \uD0DC\uADF8\uAC00 \uAE00\uC790\uB85C \uBCF4\uC785\uB2C8\uB2E4 \u2014 tNode('${String(key)}', { tags: { 0: <a href="\u2026" /> } })\uB97C \uC4F0\uC138\uC694.`
388
407
  );
389
408
  }
390
- return (0, import_core4.interpolateTranslation)(raw ?? key, params);
409
+ return (0, import_core5.interpolateTranslation)(raw ?? key, params);
391
410
  },
392
411
  [resolveRaw]
393
412
  );
394
413
  const tNode = (0, import_react10.useCallback)(
395
414
  (key, options) => {
396
415
  const raw = resolveRaw(key) ?? key;
397
- const tokens = (0, import_core4.parseRichText)(raw, options?.params);
416
+ const tokens = (0, import_core5.parseRichText)(raw, options?.params);
398
417
  return tokens.map((token, i) => {
399
418
  if (token.type === "text") return token.value;
400
419
  const element = options?.tags?.[token.index];
package/dist/index.d.cts CHANGED
@@ -75,9 +75,11 @@ interface NavigationActions {
75
75
  /** 외부 URL을 새 탭으로 열기. */
76
76
  openExternal: (url: string) => void;
77
77
  }
78
+
78
79
  /**
79
80
  * 플랫폼 네비게이션 hook.
80
81
  *
82
+ * 격리 프레임(`__bstage_bridge__` 있음)에서는 호스트에 브리지 요청을 보내고,
81
83
  * 플랫폼에 임베드된 상태에서는 PlatformBridge를 통해 네비게이션하고,
82
84
  * 로컬 dev 환경 등 BstageContext가 없을 때는 브라우저 네이티브 API로 fallback한다.
83
85
  *
package/dist/index.d.ts CHANGED
@@ -75,9 +75,11 @@ interface NavigationActions {
75
75
  /** 외부 URL을 새 탭으로 열기. */
76
76
  openExternal: (url: string) => void;
77
77
  }
78
+
78
79
  /**
79
80
  * 플랫폼 네비게이션 hook.
80
81
  *
82
+ * 격리 프레임(`__bstage_bridge__` 있음)에서는 호스트에 브리지 요청을 보내고,
81
83
  * 플랫폼에 임베드된 상태에서는 PlatformBridge를 통해 네비게이션하고,
82
84
  * 로컬 dev 환경 등 BstageContext가 없을 때는 브라우저 네이티브 API로 fallback한다.
83
85
  *
package/dist/index.js CHANGED
@@ -118,39 +118,56 @@ function registerTemplate(template) {
118
118
  }
119
119
 
120
120
  // src/hooks/useNavigation.ts
121
- import { useCallback, useContext as useContext2 } from "react";
122
- function useNavigation() {
123
- const ctx = useContext2(BstageContext);
124
- const bridge = ctx?.bridge;
125
- const navigate = useCallback(
126
- (path, params) => {
127
- if (bridge) {
128
- bridge.emit("navigate", { path, params });
121
+ import { useMemo, useContext as useContext2 } from "react";
122
+ import { getFrameBridge } from "@bstage-sdk/core";
123
+
124
+ // src/hooks/navigationActions.ts
125
+ function withQuery(path, params) {
126
+ return path + (params ? "?" + new URLSearchParams(params).toString() : "");
127
+ }
128
+ function createNavigationActions(frameBridge, platformBridge) {
129
+ if (frameBridge) {
130
+ const send = (type, payload) => {
131
+ frameBridge.request(type, payload).catch(() => {
132
+ });
133
+ };
134
+ return {
135
+ navigate: (path, params) => send("navigate", { path: withQuery(path, params) }),
136
+ goBack: () => send("back", {}),
137
+ openExternal: (url) => send("openExternal", { url })
138
+ };
139
+ }
140
+ return {
141
+ navigate: (path, params) => {
142
+ if (platformBridge) {
143
+ platformBridge.emit("navigate", { path, params });
129
144
  } else {
130
- const query = params ? "?" + new URLSearchParams(params).toString() : "";
131
- window.location.href = path + query;
145
+ window.location.href = withQuery(path, params);
132
146
  }
133
147
  },
134
- [bridge]
135
- );
136
- const goBack = useCallback(() => {
137
- if (bridge) {
138
- bridge.emit("go-back", {});
139
- } else {
140
- window.history.back();
141
- }
142
- }, [bridge]);
143
- const openExternal = useCallback(
144
- (url) => {
145
- if (bridge) {
146
- bridge.emit("open-external", { url });
148
+ goBack: () => {
149
+ if (platformBridge) {
150
+ platformBridge.emit("go-back", {});
147
151
  } else {
148
- window.open(url, "_blank");
152
+ window.history.back();
149
153
  }
150
154
  },
151
- [bridge]
152
- );
153
- return { navigate, goBack, openExternal };
155
+ openExternal: (url) => {
156
+ if (platformBridge) {
157
+ platformBridge.emit("open-external", { url });
158
+ } else {
159
+ window.open(url, "_blank");
160
+ }
161
+ }
162
+ };
163
+ }
164
+
165
+ // src/hooks/useNavigation.ts
166
+ function useNavigation() {
167
+ const ctx = useContext2(BstageContext);
168
+ const bridge = ctx?.bridge;
169
+ const frameBridge = getFrameBridge();
170
+ return useMemo(() => createNavigationActions(frameBridge, bridge), [frameBridge, bridge]);
154
171
  }
155
172
 
156
173
  // src/hooks/usePlatformEvent.ts
@@ -206,7 +223,7 @@ function hashString(str) {
206
223
  }
207
224
 
208
225
  // src/hooks/useLocale.ts
209
- import { useCallback as useCallback2, useSyncExternalStore } from "react";
226
+ import { useCallback, useSyncExternalStore } from "react";
210
227
  import { readLocale, observeLocale, DEFAULT_LANGUAGE } from "@bstage-sdk/core";
211
228
 
212
229
  // src/LocaleProvider.tsx
@@ -231,8 +248,8 @@ function BstageLocaleProvider({
231
248
  // src/hooks/useLocale.ts
232
249
  function useLocale() {
233
250
  const target = useLocaleTarget();
234
- const subscribe = useCallback2((onChange) => observeLocale(onChange, target), [target]);
235
- const getSnapshot = useCallback2(() => readLocale(target), [target]);
251
+ const subscribe = useCallback((onChange) => observeLocale(onChange, target), [target]);
252
+ const getSnapshot = useCallback(() => readLocale(target), [target]);
236
253
  const current = useSyncExternalStore(subscribe, getSnapshot, () => DEFAULT_LANGUAGE);
237
254
  return { current };
238
255
  }
@@ -272,9 +289,10 @@ function useMessages(messages) {
272
289
  }
273
290
 
274
291
  // src/hooks/useBstageTranslations.ts
275
- import { cloneElement, useCallback as useCallback3, useEffect as useEffect4, useRef as useRef3, useState as useState2 } from "react";
292
+ import { cloneElement, useCallback as useCallback2, useEffect as useEffect4, useRef as useRef3, useState as useState2 } from "react";
276
293
  import {
277
294
  fetchTranslations,
295
+ observeTranslations,
278
296
  interpolateTranslation,
279
297
  parseRichText,
280
298
  pickTranslation,
@@ -288,6 +306,8 @@ function useBstageTranslations() {
288
306
  const [dicts, setDicts] = useState2();
289
307
  const [depth, setDepth] = useState2(() => requiredDepth.get(depthKey) ?? 1);
290
308
  const pendingRef = useRef3(false);
309
+ const [translationsRevision, setTranslationsRevision] = useState2(0);
310
+ useEffect4(() => observeTranslations(() => setTranslationsRevision((n) => n + 1)), []);
291
311
  useEffect4(() => {
292
312
  setDicts(void 0);
293
313
  setDepth(requiredDepth.get(depthKey) ?? 1);
@@ -306,8 +326,8 @@ function useBstageTranslations() {
306
326
  return () => {
307
327
  active = false;
308
328
  };
309
- }, [current, target, depth]);
310
- const requestFallback = useCallback3(
329
+ }, [current, target, depth, translationsRevision]);
330
+ const requestFallback = useCallback2(
311
331
  (chainLength) => {
312
332
  if (pendingRef.current) return;
313
333
  pendingRef.current = true;
@@ -322,7 +342,7 @@ function useBstageTranslations() {
322
342
  },
323
343
  [depthKey]
324
344
  );
325
- const resolveRaw = useCallback3(
345
+ const resolveRaw = useCallback2(
326
346
  (key) => {
327
347
  const resolved = dicts ? pickTranslation(dicts, key) : void 0;
328
348
  if (resolved !== void 0) return resolved;
@@ -341,7 +361,7 @@ function useBstageTranslations() {
341
361
  },
342
362
  [dicts, current, requestFallback]
343
363
  );
344
- const t = useCallback3(
364
+ const t = useCallback2(
345
365
  (key, params) => {
346
366
  if (process.env.NODE_ENV !== "production") {
347
367
  if (typeof params === "string") {
@@ -362,7 +382,7 @@ function useBstageTranslations() {
362
382
  },
363
383
  [resolveRaw]
364
384
  );
365
- const tNode = useCallback3(
385
+ const tNode = useCallback2(
366
386
  (key, options) => {
367
387
  const raw = resolveRaw(key) ?? key;
368
388
  const tokens = parseRichText(raw, options?.params);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bstage-sdk/react",
3
- "version": "0.8.7",
3
+ "version": "0.9.1",
4
4
  "description": "bstage SDK React bindings — create b.stage templates with React",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -30,7 +30,7 @@
30
30
  "dist"
31
31
  ],
32
32
  "dependencies": {
33
- "@bstage-sdk/core": "0.8.7"
33
+ "@bstage-sdk/core": "0.9.1"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18",