@juo/orion-core 0.12.0 → 0.14.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.
Files changed (41) hide show
  1. package/dist/{ExtensionRoot-BuoY5H2A.js → ExtensionRoot-BFk-vt2J.js} +44 -16
  2. package/dist/block.d.ts +15 -3
  3. package/dist/bridge-fHXg0b-e.js +421 -0
  4. package/dist/core.js +270 -9
  5. package/dist/editor/bridge.d.ts +17 -0
  6. package/dist/editor/bridge.test.d.ts +1 -0
  7. package/dist/editor/components.d.ts +6 -0
  8. package/dist/editor/handler.d.ts +2 -3
  9. package/dist/editor/main.d.ts +7 -4
  10. package/dist/editor/messages.d.ts +86 -6
  11. package/dist/editor.js +299 -59
  12. package/dist/flows/MockWorkflowApiAdapter.d.ts +12 -0
  13. package/dist/flows/WorkflowService.d.ts +156 -0
  14. package/dist/flows/__tests__/WorkflowService.test.d.ts +1 -0
  15. package/dist/flows/__tests__/defaults.test.d.ts +1 -0
  16. package/dist/flows/__tests__/juo-workflow.test.d.ts +1 -0
  17. package/dist/flows/__tests__/overlay-behavior.test.d.ts +1 -0
  18. package/dist/flows/__tests__/theme-state-surfaces.test.d.ts +1 -0
  19. package/dist/flows/defaults.d.ts +14 -0
  20. package/dist/flows/index.d.ts +3 -0
  21. package/dist/flows/juo-workflow.d.ts +47 -0
  22. package/dist/juo-workflow-CoWvwYTn.js +545 -0
  23. package/dist/main.d.ts +5 -3
  24. package/dist/preact.js +1 -1
  25. package/dist/react.js +1 -1
  26. package/dist/{block-CFJIpH_9.js → theme-state-TW-9hD7e.js} +209 -7
  27. package/dist/theme-state.d.ts +84 -0
  28. package/dist/theme-state.locales.test.d.ts +1 -0
  29. package/dist/translation.d.ts +13 -0
  30. package/dist/translation.test.d.ts +1 -0
  31. package/dist/vue/context.d.ts +2 -0
  32. package/dist/vue.js +8 -1
  33. package/dist/web-components/ExtensionRoot.d.ts +12 -1
  34. package/dist/web-components/editor/InlineText.d.ts +4 -0
  35. package/dist/web-components/runtime/InlineText.d.ts +2 -1
  36. package/dist/web-components-editor.js +70 -21
  37. package/dist/web-components-runtime.js +39 -3
  38. package/package.json +1 -1
  39. package/dist/bridge-BPfBHSPI.js +0 -245
  40. package/dist/page-DFFhF7j8.js +0 -12
  41. package/dist/page.d.ts +0 -9
@@ -507,6 +507,24 @@ function E(i2) {
507
507
  r[Symbol.dispose] = r;
508
508
  return r;
509
509
  }
510
+ function serializeBlocks(blocks) {
511
+ return blocks.map((block) => serializeBlock(block));
512
+ }
513
+ function serializeBlock(block) {
514
+ return {
515
+ id: block.id,
516
+ type: block.type,
517
+ props: JSON.parse(JSON.stringify(block.props)),
518
+ slots: Object.fromEntries(
519
+ Object.entries(block.slots ?? {}).map(([key, value]) => [
520
+ key,
521
+ Array.isArray(value) ? value.map(
522
+ (v2) => typeof v2 === "string" ? v2 : serializeBlock(v2)
523
+ ) : typeof value === "string" ? value : serializeBlock(value)
524
+ ])
525
+ )
526
+ };
527
+ }
510
528
  function createSelectedBlock() {
511
529
  const selected = d(null);
512
530
  function setSelection(block) {
@@ -571,8 +589,13 @@ function withWrapper(fn) {
571
589
  return wrapper;
572
590
  };
573
591
  }
592
+ const registerBlockListeners = [];
574
593
  function registerBlock(block) {
575
594
  blockDefinitions.set(block.name, block);
595
+ registerBlockListeners.forEach((cb) => cb(block.name, block));
596
+ }
597
+ function onRegisterBlock(cb) {
598
+ registerBlockListeners.push(cb);
576
599
  }
577
600
  function defineBlock(name, opts) {
578
601
  const definition = {
@@ -581,7 +604,8 @@ function defineBlock(name, opts) {
581
604
  schema: opts.schema,
582
605
  initialValue: opts.initialValue,
583
606
  render: opts.renderer,
584
- presets: opts.presets
607
+ presets: opts.presets,
608
+ locales: opts.locales
585
609
  };
586
610
  return definition;
587
611
  }
@@ -633,8 +657,10 @@ function createCeRenderer(name) {
633
657
  return (block) => {
634
658
  const wrapper = document.createElement("div");
635
659
  wrapper.setAttribute("data-block-id", block.id);
660
+ wrapper.setAttribute("data-block-type", block.type);
636
661
  const el = document.createElement(name);
637
662
  el.setAttribute("data-block-id", block.id);
663
+ el.setAttribute("data-block-type", block.type);
638
664
  Object.entries(block.props).forEach(([key, value]) => {
639
665
  el[key] = value;
640
666
  });
@@ -700,11 +726,183 @@ function createBlockInstanceFromObject(input) {
700
726
  function createBlockInstanceFromJSON(input) {
701
727
  return createBlockInstanceFromObject(JSON.parse(input));
702
728
  }
729
+ const DEFAULT_GLOBAL_STYLES = {
730
+ volume: "comfort",
731
+ style: "ghost",
732
+ corners: "round",
733
+ buttonCorners: "round",
734
+ thumbnailCorners: "circle",
735
+ theme: "preset",
736
+ themeType: "neutral",
737
+ colors: {
738
+ accent: "#000000",
739
+ secondary: "#000000",
740
+ tint: "#FFFFFF",
741
+ callout: "#F5F5F5",
742
+ success: "#287a25",
743
+ error: "#a93c3c",
744
+ information: "#0075a3",
745
+ warning: "#8a5e00",
746
+ background: "#FFFFFF"
747
+ }
748
+ };
749
+ const ThemeStateContext = createContext("theme-state");
750
+ function normalizeLocale(locale) {
751
+ return locale.trim().toLowerCase().split("-")[0] || "en";
752
+ }
753
+ function toStringRecord(input) {
754
+ if (input == null)
755
+ return {};
756
+ return Object.fromEntries(
757
+ Object.entries(input).filter(([, value]) => typeof value === "string")
758
+ );
759
+ }
760
+ function parseBlockLocaleFile(file) {
761
+ if (file == null) {
762
+ return { defaults: {}, modes: {} };
763
+ }
764
+ const entries = Object.entries(file).filter(
765
+ ([key, value]) => key !== "overrides" && typeof value === "string"
766
+ );
767
+ const topLevel = Object.fromEntries(entries);
768
+ const overrides = toStringRecord(file.overrides);
769
+ return {
770
+ defaults: { ...topLevel, ...overrides },
771
+ modes: {
772
+ ...Object.fromEntries(
773
+ Object.keys(topLevel).map((key) => [key, "default"])
774
+ ),
775
+ ...Object.fromEntries(
776
+ Object.keys(overrides).map((key) => [key, "override"])
777
+ )
778
+ }
779
+ };
780
+ }
781
+ function indexOverrides(overrides) {
782
+ const indexed = {
783
+ theme: {},
784
+ blocks: {}
785
+ };
786
+ for (const item of overrides) {
787
+ if (item.scope.kind === "theme") {
788
+ indexed.theme[item.key] = item.value;
789
+ continue;
790
+ }
791
+ if (indexed.blocks[item.scope.blockId] == null) {
792
+ indexed.blocks[item.scope.blockId] = {};
793
+ }
794
+ indexed.blocks[item.scope.blockId][item.key] = item.value;
795
+ }
796
+ return indexed;
797
+ }
798
+ function createThemeState(deps) {
799
+ const surfaces = {
800
+ page: { blocks: d([]) },
801
+ overlay: { blocks: d([]) }
802
+ };
803
+ const locale = d("en");
804
+ const catalogs = d(null);
805
+ const globalStyles = d(
806
+ deps.initialGlobalStyles ?? DEFAULT_GLOBAL_STYLES
807
+ );
808
+ function setGlobalStyles(styles) {
809
+ globalStyles.value = styles;
810
+ }
811
+ async function collectBlockDefaults(loc) {
812
+ const nextDefaults = {};
813
+ const nextModes = {};
814
+ for (const block of getDefinedBlocks()) {
815
+ if (block.locales == null)
816
+ continue;
817
+ let file = null;
818
+ try {
819
+ file = await block.locales.load(loc);
820
+ } catch {
821
+ file = null;
822
+ }
823
+ const parsed = parseBlockLocaleFile(file);
824
+ nextDefaults[block.name] = parsed.defaults;
825
+ nextModes[block.name] = parsed.modes;
826
+ }
827
+ return { defaults: nextDefaults, modes: nextModes };
828
+ }
829
+ async function setLocale(nextLocaleRaw) {
830
+ var _a;
831
+ const nextLocale = normalizeLocale(nextLocaleRaw);
832
+ const [blockData, loadedOverrides] = await Promise.all([
833
+ collectBlockDefaults(nextLocale),
834
+ ((_a = deps.translations) == null ? void 0 : _a.resolveTranslations(nextLocale).catch(() => [])) ?? Promise.resolve([])
835
+ ]);
836
+ const overrides = loadedOverrides.filter(
837
+ (item) => normalizeLocale(item.locale) === nextLocale
838
+ );
839
+ const indexed = indexOverrides(overrides);
840
+ catalogs.value = {
841
+ theme: {
842
+ defaults: {},
843
+ overrides: indexed.theme
844
+ },
845
+ blocks: {
846
+ defaults: blockData.defaults,
847
+ modes: blockData.modes,
848
+ overrides: indexed.blocks
849
+ }
850
+ };
851
+ locale.value = nextLocale;
852
+ }
853
+ async function resolve(surface, id, defaultBlock) {
854
+ surfaces[surface].blocks.value = [];
855
+ const result = await deps.resolve(surface, id, defaultBlock);
856
+ surfaces[surface].blocks.value = [
857
+ ...result.blocks.map((block) => createBlockInstanceFromObject(block))
858
+ ];
859
+ return result;
860
+ }
861
+ onRegisterBlock(async (_2, block) => {
862
+ if (block.locales == null || catalogs.value == null)
863
+ return;
864
+ const localeAtLoadStart = locale.value;
865
+ let file = null;
866
+ try {
867
+ file = await block.locales.load(localeAtLoadStart);
868
+ } catch {
869
+ file = null;
870
+ }
871
+ if (catalogs.value == null || locale.value !== localeAtLoadStart)
872
+ return;
873
+ const parsed = parseBlockLocaleFile(file);
874
+ const current = catalogs.value;
875
+ catalogs.value = {
876
+ ...current,
877
+ blocks: {
878
+ ...current.blocks,
879
+ defaults: {
880
+ ...current.blocks.defaults,
881
+ [block.name]: parsed.defaults
882
+ },
883
+ modes: {
884
+ ...current.blocks.modes,
885
+ [block.name]: parsed.modes
886
+ }
887
+ }
888
+ };
889
+ });
890
+ return {
891
+ page: surfaces.page,
892
+ overlay: surfaces.overlay,
893
+ locales: { locale, catalogs, setLocale },
894
+ globalStyles,
895
+ setGlobalStyles,
896
+ resolve
897
+ };
898
+ }
703
899
  export {
704
900
  BlockWrapperEvent as B,
705
901
  ContextRequestEvent as C,
902
+ DEFAULT_GLOBAL_STYLES as D,
706
903
  E,
707
904
  SelectedBlockContext as S,
905
+ ThemeStateContext as T,
708
906
  createBlockInstance as a,
709
907
  createBlockInstanceFromJSON as b,
710
908
  createContext as c,
@@ -716,13 +914,17 @@ export {
716
914
  getDefinedBlocks as i,
717
915
  withWrapper as j,
718
916
  createSelectedBlock as k,
719
- ContextProvideEvent as l,
720
- injectContext as m,
721
- n,
722
- ContextRoot as o,
917
+ createThemeState as l,
918
+ indexOverrides as m,
919
+ ContextProvideEvent as n,
920
+ injectContext as o,
723
921
  provideContext as p,
922
+ subscribeContext as q,
724
923
  registerBlock as r,
725
- subscribeContext as s,
924
+ serializeBlocks as s,
925
+ n as t,
726
926
  u,
727
- w
927
+ ContextRoot as v,
928
+ w,
929
+ onRegisterBlock as x
728
930
  };
@@ -0,0 +1,84 @@
1
+ import { ReadonlySignal, Signal } from '@preact/signals-core';
2
+ import { Block, BlockInstance } from './block';
3
+ export type ThemeSurface = "page" | "overlay";
4
+ export type GlobalStyleColors = {
5
+ accent: string;
6
+ secondary: string;
7
+ tint: string;
8
+ callout: string;
9
+ success: string;
10
+ error: string;
11
+ information: string;
12
+ warning: string;
13
+ background: string;
14
+ };
15
+ export type ThemeType = "neutral" | "warm" | "cold";
16
+ export type GlobalStyles = {
17
+ volume: "compact" | "comfort" | "spacious";
18
+ style: "bare" | "ghost" | "tinted" | "solid" | "layered";
19
+ corners: "sharp" | "soft" | "round" | "pill";
20
+ buttonCorners: "sharp" | "round" | "circle";
21
+ thumbnailCorners: "sharp" | "round" | "circle";
22
+ theme: "preset" | "custom";
23
+ themeType: ThemeType;
24
+ colors: GlobalStyleColors;
25
+ };
26
+ export declare const DEFAULT_GLOBAL_STYLES: GlobalStyles;
27
+ export type ThemeSurfaceState = {
28
+ blocks: Signal<BlockInstance[]>;
29
+ };
30
+ export type TranslationMode = "override" | "default";
31
+ export type TranslationScope = {
32
+ kind: "theme";
33
+ } | {
34
+ kind: "block";
35
+ blockId: string;
36
+ };
37
+ export type TranslationOverride = {
38
+ locale: string;
39
+ key: string;
40
+ value: string;
41
+ scope: TranslationScope;
42
+ };
43
+ export type TranslationCatalogs = {
44
+ theme: {
45
+ defaults: Record<string, string>;
46
+ overrides: Record<string, string>;
47
+ };
48
+ blocks: {
49
+ defaults: Record<string, Record<string, string>>;
50
+ modes: Record<string, Record<string, TranslationMode>>;
51
+ overrides: Record<string, Record<string, string>>;
52
+ };
53
+ };
54
+ export type ThemeLocaleState = {
55
+ locale: ReadonlySignal<string>;
56
+ catalogs: ReadonlySignal<TranslationCatalogs | null>;
57
+ setLocale: (locale: string) => Promise<void>;
58
+ };
59
+ export type ThemeState = {
60
+ page: ThemeSurfaceState;
61
+ overlay: ThemeSurfaceState;
62
+ locales: ThemeLocaleState;
63
+ globalStyles: ReadonlySignal<GlobalStyles>;
64
+ setGlobalStyles: (styles: GlobalStyles) => void;
65
+ resolve: (surface: ThemeSurface, id: string, defaultBlock: string) => Promise<{
66
+ blocks: Block[];
67
+ }>;
68
+ };
69
+ export declare const ThemeStateContext: {
70
+ __context__: ThemeState;
71
+ };
72
+ export declare function indexOverrides(overrides: TranslationOverride[]): {
73
+ theme: Record<string, string>;
74
+ blocks: Record<string, Record<string, string>>;
75
+ };
76
+ export declare function createThemeState(deps: {
77
+ resolve: (surface: ThemeSurface, id: string, defaultBlock: string) => Promise<{
78
+ blocks: Block[];
79
+ }>;
80
+ translations?: {
81
+ resolveTranslations: (locale: string) => Promise<TranslationOverride[]>;
82
+ };
83
+ initialGlobalStyles?: GlobalStyles;
84
+ }): ThemeState;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { ReadonlySignal } from '@preact/signals-core';
2
+ import { ThemeLocaleState } from './theme-state';
3
+ export interface TranslationService {
4
+ readonly locale: ReadonlySignal<string>;
5
+ resolve(blockType: string | null, blockId: string | null, key: string): string;
6
+ }
7
+ export type TranslationServiceOptions = {
8
+ loadDefaultTranslations?: (locale: string) => Promise<Record<string, string>>;
9
+ };
10
+ export declare const TranslationContext: {
11
+ __context__: TranslationService;
12
+ };
13
+ export declare function createTranslationService(locales: ThemeLocaleState, options?: TranslationServiceOptions): TranslationService;
@@ -0,0 +1 @@
1
+ export {};
@@ -8,5 +8,7 @@ export declare function useContext<C extends UnknownContext>(context: C): Wrap<C
8
8
  export declare function useProvideContext<C extends UnknownContext>(context: C, init: ContextType<C>): void;
9
9
  type Wrap<T> = T extends Signal<infer V> ? Ref<V> : T extends Function ? T : T extends Record<any, any> ? {
10
10
  [K in keyof T]: Wrap<T[K]>;
11
+ } & {
12
+ $: T;
11
13
  } : T;
12
14
  export {};
package/dist/vue.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { toValue, watchEffect, customRef, defineComponent, ref, getCurrentInstance, onMounted, provide, h, renderSlot, inject, computed, createApp, useHost, defineCustomElement } from "vue";
2
2
  import { signal, effect, injectContext, provideContext, createCeRenderer } from "@juo/orion-core";
3
- import { c as createEditorBridge } from "./bridge-BPfBHSPI.js";
3
+ import { c as createEditorBridge } from "./bridge-fHXg0b-e.js";
4
4
  const signalsMap = /* @__PURE__ */ new WeakMap();
5
5
  function toSignal(ref2) {
6
6
  if (!signalsMap.has(ref2)) {
@@ -97,9 +97,15 @@ function wrap(obj) {
97
97
  return new Proxy(obj, {
98
98
  get(target, key2) {
99
99
  const val = target[key2];
100
+ if (key2 === "$") {
101
+ return target;
102
+ }
100
103
  if (typeof val === "object" && val != null && "brand" in val) {
101
104
  return toRef(val);
102
105
  }
106
+ if (typeof val === "object" && val != null && !Array.isArray(val) && typeof val !== "function") {
107
+ return wrap(val);
108
+ }
103
109
  return val;
104
110
  }
105
111
  });
@@ -164,6 +170,7 @@ function createVueCeRenderer(name, component, { shadowRoot = true } = {}) {
164
170
  slots: component.slots
165
171
  }
166
172
  );
173
+ C.styles = component.styles;
167
174
  customElements.define(name, defineCustomElement(C, { shadowRoot }));
168
175
  return createCeRenderer(name);
169
176
  }
@@ -1,11 +1,22 @@
1
1
  export default class ExtensionRoot extends HTMLElement {
2
2
  private state;
3
- private unsubscribeContext?;
3
+ private themeState;
4
+ private unsubscribeThemeContext?;
4
5
  private disposeEffect?;
6
+ /**
7
+ * Optional function to wrap each rendered block element.
8
+ * Called with the rendered block HTMLElement, must return an HTMLElement.
9
+ * When set, the wrapper sits between the editor wrapper (outer) and the actual block (inner).
10
+ * Must be set before blocks are first rendered; changing it afterwards has no effect
11
+ * on already-cached block wrappers.
12
+ */
13
+ blockWrapper: ((rendered: HTMLElement) => HTMLElement) | null;
5
14
  static get observedAttributes(): string[];
6
15
  constructor();
7
16
  private wrapperCache;
8
17
  private withWrapper;
18
+ private getSurface;
19
+ private setStateFromThemeState;
9
20
  connectedCallback(): void;
10
21
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
11
22
  disconnectedCallback(): void;
@@ -1,13 +1,17 @@
1
1
  export default class InlineText extends HTMLElement {
2
2
  private editorBridge;
3
+ private translationService;
3
4
  private propName;
4
5
  private blockId;
6
+ private blockType;
5
7
  private boundHandleBlur;
6
8
  private boundHandlePointerDown;
7
9
  private lastValue;
10
+ private dispose?;
8
11
  static get observedAttributes(): string[];
9
12
  constructor();
10
13
  connectedCallback(): void;
14
+ private get isReadonly();
11
15
  private initializeEditorMode;
12
16
  private handlePointerDown;
13
17
  private handleBlur;
@@ -1,4 +1,5 @@
1
1
  export default class InlineText extends HTMLElement {
2
- constructor();
2
+ private dispose?;
3
3
  connectedCallback(): void;
4
+ disconnectedCallback(): void;
4
5
  }
@@ -4,63 +4,110 @@ var __publicField = (obj, key, value) => {
4
4
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
5
  return value;
6
6
  };
7
- import { o as ContextRoot } from "./block-CFJIpH_9.js";
8
- import { E as ExtensionRoot, B as Block } from "./ExtensionRoot-BuoY5H2A.js";
9
- import { c as createEditorBridge, a as createUpdateBlockPropsMessage } from "./bridge-BPfBHSPI.js";
7
+ import { o as injectContext, E, v as ContextRoot } from "./theme-state-TW-9hD7e.js";
8
+ import { E as ExtensionRoot, B as Block } from "./ExtensionRoot-BFk-vt2J.js";
9
+ import { c as createEditorBridge, a as createFocusInlineTextMessage, b as createUpdateBlockTranslationMessage } from "./bridge-fHXg0b-e.js";
10
+ import { T as TranslationContext } from "./juo-workflow-CoWvwYTn.js";
10
11
  const _InlineText = class _InlineText extends HTMLElement {
11
12
  constructor() {
12
13
  super();
13
14
  __publicField(this, "editorBridge", null);
15
+ __publicField(this, "translationService", null);
14
16
  __publicField(this, "propName", null);
15
17
  __publicField(this, "blockId", null);
18
+ __publicField(this, "blockType", null);
16
19
  __publicField(this, "boundHandleBlur", this.handleBlur.bind(this));
17
20
  __publicField(this, "boundHandlePointerDown", this.handlePointerDown.bind(this));
18
21
  __publicField(this, "lastValue", null);
22
+ __publicField(this, "dispose");
19
23
  }
20
24
  static get observedAttributes() {
21
- return ["prop"];
25
+ return ["prop", "readonly"];
22
26
  }
23
27
  connectedCallback() {
24
28
  this.style.display = "inline-block";
29
+ this.style.overflowWrap = "anywhere";
25
30
  this.propName = this.getAttribute("prop");
26
31
  if (!this.propName) {
27
32
  console.warn("juo-text: 'prop' attribute is required");
28
33
  return;
29
34
  }
30
- let blockWrapper = this.closest("[data-block-id]");
35
+ let blockWrapper = this.closest("[data-block-type]");
31
36
  if (!blockWrapper) {
32
37
  const rootNode = this.getRootNode();
33
38
  if (rootNode instanceof ShadowRoot && rootNode.host) {
34
- blockWrapper = rootNode.host.closest("[data-block-id]");
39
+ blockWrapper = rootNode.host.closest("[data-block-type]");
35
40
  }
36
41
  }
37
42
  if (!blockWrapper) {
38
- console.warn("juo-text: Could not find parent block with data-block-id");
43
+ console.warn(
44
+ "juo-text: Could not find parent block with data-block-type"
45
+ );
39
46
  return;
40
47
  }
41
48
  this.blockId = blockWrapper.getAttribute("data-block-id");
49
+ this.blockType = blockWrapper.getAttribute("data-block-type");
42
50
  if (!this.blockId) {
43
51
  console.warn("juo-text: Parent block has no data-block-id attribute");
44
52
  return;
45
53
  }
54
+ if (!this.blockType) {
55
+ console.warn("juo-text: Parent block has no data-block-type attribute");
56
+ return;
57
+ }
58
+ this.translationService = injectContext(this, TranslationContext);
46
59
  this.initializeEditorMode();
47
60
  }
61
+ get isReadonly() {
62
+ return this.hasAttribute("readonly");
63
+ }
48
64
  initializeEditorMode() {
49
65
  this.editorBridge = createEditorBridge();
50
66
  this.contentEditable = "false";
51
- this.style.cursor = "text";
67
+ if (!this.isReadonly) {
68
+ this.style.cursor = "text";
69
+ this.style.borderRadius = "2px";
70
+ this.style.outline = "0.5px solid transparent";
71
+ this.style.outlineOffset = "2px";
72
+ }
52
73
  this.style.width = "100%";
53
- this.style.borderRadius = "2px";
54
- this.style.outline = "0.5px solid transparent";
55
- this.style.outlineOffset = "2px";
56
74
  this.style.overflowWrap = "anywhere";
57
75
  this.style.whiteSpace = "pre-wrap";
58
- this.injectStyles();
76
+ if (!this.isReadonly) {
77
+ this.injectStyles();
78
+ }
59
79
  this.addEventListener("blur", this.boundHandleBlur);
60
80
  this.addEventListener("pointerdown", this.boundHandlePointerDown);
61
81
  this.lastValue = this.textContent || "";
82
+ if (this.translationService && this.propName && this.blockType && this.blockId) {
83
+ const key = this.propName;
84
+ const fallbackText = this.textContent ?? "";
85
+ this.dispose = E(() => {
86
+ const service = this.translationService;
87
+ if (!service)
88
+ return;
89
+ void service.locale.value;
90
+ const resolved = service.resolve(this.blockType, this.blockId, key);
91
+ const value = resolved === key && fallbackText.trim().length > 0 ? fallbackText : resolved;
92
+ this.textContent = value;
93
+ this.lastValue = value;
94
+ });
95
+ }
62
96
  }
63
97
  handlePointerDown() {
98
+ if (this.isReadonly)
99
+ return;
100
+ if (this.contentEditable === "plaintext-only")
101
+ return;
102
+ if (this.editorBridge && this.blockId && this.propName) {
103
+ this.editorBridge.sendMessage(
104
+ createFocusInlineTextMessage(
105
+ { blockId: this.blockId, key: this.propName },
106
+ this.blockId
107
+ )
108
+ );
109
+ }
110
+ this.textContent = this.lastValue ?? "";
64
111
  this.contentEditable = "plaintext-only";
65
112
  }
66
113
  handleBlur() {
@@ -90,23 +137,21 @@ const _InlineText = class _InlineText extends HTMLElement {
90
137
  _InlineText.injectedRoots.add(root);
91
138
  }
92
139
  sendUpdate() {
93
- if (!this.editorBridge || !this.blockId || !this.propName) {
140
+ var _a;
141
+ if (!this.editorBridge || !this.blockId || !this.blockType || !this.propName) {
94
142
  return;
95
143
  }
96
144
  const newValue = this.textContent ?? "";
97
- if (newValue.trim() === "" && this.lastValue !== null && this.lastValue !== "") {
98
- this.textContent = this.lastValue;
99
- return;
100
- }
101
145
  if (this.lastValue === newValue) {
102
146
  return;
103
147
  }
104
- const message = createUpdateBlockPropsMessage(
148
+ const message = createUpdateBlockTranslationMessage(
105
149
  {
106
150
  blockId: this.blockId,
107
- props: {
108
- [this.propName]: newValue
109
- }
151
+ blockType: this.blockType,
152
+ key: this.propName,
153
+ value: newValue,
154
+ locale: (_a = this.translationService) == null ? void 0 : _a.locale.value
110
155
  },
111
156
  this.blockId
112
157
  );
@@ -119,9 +164,13 @@ const _InlineText = class _InlineText extends HTMLElement {
119
164
  }
120
165
  }
121
166
  disconnectedCallback() {
167
+ var _a;
122
168
  this.removeEventListener("blur", this.boundHandleBlur);
123
169
  this.removeEventListener("pointerdown", this.boundHandlePointerDown);
170
+ (_a = this.dispose) == null ? void 0 : _a.call(this);
171
+ this.dispose = void 0;
124
172
  this.editorBridge = null;
173
+ this.translationService = null;
125
174
  }
126
175
  };
127
176
  __publicField(_InlineText, "injectedRoots", /* @__PURE__ */ new WeakSet());
@@ -1,12 +1,48 @@
1
- import { o as ContextRoot } from "./block-CFJIpH_9.js";
2
- import { E as ExtensionRoot, B as Block } from "./ExtensionRoot-BuoY5H2A.js";
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => {
4
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ return value;
6
+ };
7
+ import { o as injectContext, E, v as ContextRoot } from "./theme-state-TW-9hD7e.js";
8
+ import { E as ExtensionRoot, B as Block } from "./ExtensionRoot-BFk-vt2J.js";
9
+ import { T as TranslationContext } from "./juo-workflow-CoWvwYTn.js";
3
10
  class InlineText extends HTMLElement {
4
11
  constructor() {
5
- super();
12
+ super(...arguments);
13
+ __publicField(this, "dispose");
6
14
  }
7
15
  connectedCallback() {
8
16
  this.style.display = "inline-block";
9
17
  this.style.overflowWrap = "anywhere";
18
+ const key = this.getAttribute("prop");
19
+ if (!key)
20
+ return;
21
+ let blockEl = this.closest("[data-block-type]");
22
+ if (!blockEl) {
23
+ const root = this.getRootNode();
24
+ if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
25
+ blockEl = root.host.closest("[data-block-type]");
26
+ }
27
+ }
28
+ const blockType = (blockEl == null ? void 0 : blockEl.getAttribute("data-block-type")) ?? null;
29
+ const blockId = (blockEl == null ? void 0 : blockEl.getAttribute("data-block-id")) ?? null;
30
+ const service = injectContext(this, TranslationContext);
31
+ const fallbackText = this.textContent ?? "";
32
+ this.dispose = E(() => {
33
+ void service.locale.value;
34
+ const resolved = service.resolve(blockType, blockId, key);
35
+ const value = resolved === key && fallbackText.trim().length > 0 ? fallbackText : resolved;
36
+ this.textContent = value;
37
+ if (this.hasAttribute("hide-parent-if-empty") && this.parentElement) {
38
+ this.parentElement.hidden = value.trim() === "";
39
+ }
40
+ });
41
+ }
42
+ disconnectedCallback() {
43
+ var _a;
44
+ (_a = this.dispose) == null ? void 0 : _a.call(this);
45
+ this.dispose = void 0;
10
46
  }
11
47
  }
12
48
  if (customElements.get("juo-context-root") == null) {