@floegence/floe-webapp-core 0.38.0 → 0.39.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.
@@ -1,13 +1,14 @@
1
- import { use as L, effect as O, className as A, style as D, template as F } from "solid-js/web";
2
- import { onMount as V, onCleanup as b, createEffect as g } from "solid-js";
3
- import { useTheme as q } from "../../context/ThemeContext.js";
4
- import { useResizeObserver as w } from "../../hooks/useResizeObserver.js";
1
+ import { use as z, effect as F, className as L, style as O, template as A } from "solid-js/web";
2
+ import { onMount as D, onCleanup as V, createEffect as g } from "solid-js";
3
+ import { useTheme as b } from "../../context/ThemeContext.js";
4
+ import { useResizeObserver as q } from "../../hooks/useResizeObserver.js";
5
5
  import "monaco-editor/min/vs/editor/editor.main.css";
6
- import { resolveCodeEditorLanguageSpec as U } from "./languages.js";
7
- import { ensureMonacoEnvironment as p } from "./monacoEnvironment.js";
8
- import { loadMonacoEditorApi as N } from "./monacoStandaloneRuntime.js";
9
- var _ = /* @__PURE__ */ F("<div>");
10
- const T = {
6
+ import { resolveCodeEditorLanguageSpec as w } from "./languages.js";
7
+ import { applyFloeMonacoTheme as U } from "./monacoTheme.js";
8
+ import { ensureMonacoEnvironment as N } from "./monacoEnvironment.js";
9
+ import { loadMonacoEditorApi as P } from "./monacoStandaloneRuntime.js";
10
+ var _ = /* @__PURE__ */ A("<div>");
11
+ const I = {
11
12
  readOnly: !0,
12
13
  automaticLayout: !1,
13
14
  minimap: {
@@ -20,97 +21,98 @@ const T = {
20
21
  fontFamily: "var(--font-mono)"
21
22
  };
22
23
  let $ = 0;
23
- function k(t, d, a) {
24
- return t.Uri.parse(`inmemory://model/${d}/${encodeURIComponent(a)}`);
24
+ function B(t, c, r) {
25
+ return t.Uri.parse(`inmemory://model/${c}/${encodeURIComponent(r)}`);
25
26
  }
26
- function B(t, d) {
27
- if (!t || !d) return "";
28
- const a = t.getSelection();
29
- return !a || a.isEmpty() ? "" : d.getValueInRange(a);
27
+ function H(t, c) {
28
+ if (!t || !c) return "";
29
+ const r = t.getSelection();
30
+ return !r || r.isEmpty() ? "" : c.getValueInRange(r);
30
31
  }
31
- function X(t) {
32
- const d = q();
33
- let a;
32
+ function Z(t) {
33
+ const c = b();
34
+ let r;
34
35
  const x = ++$;
35
- let l, n, o, s, y = null, v = 0;
36
- const R = w(() => a), S = () => {
37
- l && l.editor.setTheme(d.resolvedTheme() === "dark" ? "vs-dark" : "vs");
36
+ let l, n, o, u, y = null, h = 0;
37
+ const R = q(() => r), S = () => {
38
+ const e = c.resolvedTheme(), i = c.shellPreset();
39
+ l && U(l.editor, e, i);
38
40
  }, m = () => !n || !o ? null : {
39
41
  editor: n,
40
42
  model: o,
41
43
  getValue: () => n.getValue(),
42
- getSelectedText: () => B(n, o),
44
+ getSelectedText: () => H(n, o),
43
45
  focus: () => n.focus()
44
46
  }, C = () => {
45
47
  const e = m();
46
48
  if (!e) return;
47
- const r = e.model.uri.toString();
48
- r !== y && (y = r, t.onReady?.(e));
49
+ const i = e.model.uri.toString();
50
+ i !== y && (y = i, t.onReady?.(e));
49
51
  }, M = () => {
50
52
  const e = m();
51
53
  e && t.onSelectionChange?.(e.getSelectedText(), e);
52
- }, E = async () => {
54
+ }, T = async () => {
53
55
  if (!n || !l) return;
54
- const e = ++v, r = U(t.language);
55
- let i = r.id;
56
+ const e = ++h, i = w(t.language);
57
+ let a = i.id;
56
58
  try {
57
- await r.load?.();
59
+ await i.load?.();
58
60
  } catch {
59
- if (e !== v) return;
60
- i = "plaintext";
61
+ if (e !== h) return;
62
+ a = "plaintext";
61
63
  }
62
- if (!n || e !== v) return;
63
- const u = k(l, x, t.path);
64
- if (o && o.uri.toString() === u.toString()) {
65
- o.getLanguageId() !== i && l.editor.setModelLanguage(o, i), o.getValue() !== t.value && o.setValue(t.value), C(), M();
64
+ if (!n || e !== h) return;
65
+ const d = B(l, x, t.path);
66
+ if (o && o.uri.toString() === d.toString()) {
67
+ o.getLanguageId() !== a && l.editor.setModelLanguage(o, a), o.getValue() !== t.value && o.setValue(t.value), C(), M();
66
68
  return;
67
69
  }
68
- const c = l.editor.createModel(t.value, i, u);
69
- o?.dispose(), o = c, n.setModel(o), C(), M();
70
+ const s = l.editor.createModel(t.value, a, d);
71
+ o?.dispose(), o = s, n.setModel(o), C(), M();
70
72
  };
71
- return V(() => {
72
- let e = !1, r, i;
73
+ return D(() => {
74
+ let e = !1, i, a;
73
75
  (async () => {
74
- if (!a || (p(), l = await N(t.runtimeOptions), e || !a) || (n = l.editor.create(a, {
76
+ if (!r || (N(), l = await P(t.runtimeOptions), e || !r) || (n = l.editor.create(r, {
75
77
  model: null,
76
- ...T,
78
+ ...I,
77
79
  ...t.options ?? {}
78
- }), S(), await E(), e || !n)) return;
79
- const c = t.onContentChange, I = t.onChange, z = t.onSelectionChange;
80
- r = n.onDidChangeModelContent((f) => {
81
- const h = m();
82
- h && (c?.(f, h), I && I(h.getValue()));
83
- }), i = n.onDidChangeCursorSelection(() => {
80
+ }), S(), await T(), e || !n)) return;
81
+ const s = t.onContentChange, E = t.onChange, p = t.onSelectionChange;
82
+ i = n.onDidChangeModelContent((f) => {
83
+ const v = m();
84
+ v && (s?.(f, v), E && E(v.getValue()));
85
+ }), a = n.onDidChangeCursorSelection(() => {
84
86
  const f = m();
85
- f && z?.(f.getSelectedText(), f);
87
+ f && p?.(f.getSelectedText(), f);
86
88
  });
87
- })().catch((c) => {
88
- console.error("Failed to initialize Monaco editor runtime", c);
89
- }), b(() => {
90
- e = !0, r?.dispose(), i?.dispose(), s && cancelAnimationFrame(s), n?.dispose(), o?.dispose(), l = void 0, n = void 0, o = void 0;
89
+ })().catch((s) => {
90
+ console.error("Failed to initialize Monaco editor runtime", s);
91
+ }), V(() => {
92
+ e = !0, i?.dispose(), a?.dispose(), u && cancelAnimationFrame(u), n?.dispose(), o?.dispose(), l = void 0, n = void 0, o = void 0;
91
93
  });
92
94
  }), g(() => {
93
95
  S();
94
96
  }), g(() => {
95
97
  n && n.updateOptions({
96
- ...T,
98
+ ...I,
97
99
  ...t.options ?? {}
98
100
  });
99
101
  }), g(() => {
100
- t.path, t.language, t.value, E();
102
+ t.path, t.language, t.value, T();
101
103
  }), g(() => {
102
104
  const e = R();
103
- !e || !n || (s && cancelAnimationFrame(s), s = requestAnimationFrame(() => {
105
+ !e || !n || (u && cancelAnimationFrame(u), u = requestAnimationFrame(() => {
104
106
  n?.layout({
105
107
  width: e.width,
106
108
  height: e.height
107
109
  });
108
110
  }));
109
111
  }), (() => {
110
- var e = _(), r = a;
111
- return typeof r == "function" ? L(r, e) : a = e, O((i) => {
112
- var u = t.class, c = t.style;
113
- return u !== i.e && A(e, i.e = u), i.t = D(e, c, i.t), i;
112
+ var e = _(), i = r;
113
+ return typeof i == "function" ? z(i, e) : r = e, F((a) => {
114
+ var d = t.class, s = t.style;
115
+ return d !== a.e && L(e, a.e = d), a.t = O(e, s, a.t), a;
114
116
  }, {
115
117
  e: void 0,
116
118
  t: void 0
@@ -118,5 +120,5 @@ function X(t) {
118
120
  })();
119
121
  }
120
122
  export {
121
- X as CodeEditor
123
+ Z as CodeEditor
122
124
  };
@@ -1,3 +1,4 @@
1
1
  export { CodeEditor, type CodeEditorProps, type CodeEditorApi } from './CodeEditor';
2
- export { resolveCodeEditorLanguageSpec, isCodeEditorLanguageSupported, type CodeEditorLanguageSpec } from './languages';
2
+ export { resolveCodeEditorLanguageSpec, isCodeEditorLanguageSupported, type CodeEditorLanguageSpec, } from './languages';
3
+ export { applyFloeMonacoTheme, resolveFloeMonacoTheme, type MonacoThemeData, type MonacoThemeRegistry, type ResolvedFloeMonacoTheme, } from './monacoTheme';
3
4
  export { DEFAULT_MONACO_RUNTIME_PROFILE, DEFAULT_MONACO_STANDALONE_FEATURES, MONACO_RUNTIME_BLUEPRINTS, normalizeMonacoRuntimeFeatureSet, resolveMonacoRuntimeProfile, resolveMonacoRuntimeRequest, type CodeEditorRuntimeOptions, type MonacoRuntimeProfileName, type MonacoStandaloneRuntimeBlueprint, type MonacoStandaloneRuntimeModuleDescriptor, type MonacoRuntimeFeatureSet, type ResolvedMonacoRuntimeRequest, } from './monacoStandaloneRuntime';
@@ -0,0 +1,17 @@
1
+ import type { FloeMonacoThemeDefinition, FloeMonacoTokenRule, FloeThemePreset } from '../../styles/themes';
2
+ export interface MonacoThemeData {
3
+ base: 'vs' | 'vs-dark';
4
+ inherit: boolean;
5
+ rules: FloeMonacoTokenRule[];
6
+ colors: Record<string, string>;
7
+ }
8
+ export interface MonacoThemeRegistry {
9
+ defineTheme: (themeName: string, themeData: MonacoThemeData) => void;
10
+ setTheme: (themeName: string) => void;
11
+ }
12
+ export interface ResolvedFloeMonacoTheme {
13
+ name: string;
14
+ definition?: FloeMonacoThemeDefinition;
15
+ }
16
+ export declare function resolveFloeMonacoTheme(mode: 'light' | 'dark', preset?: FloeThemePreset): ResolvedFloeMonacoTheme;
17
+ export declare function applyFloeMonacoTheme(registry: MonacoThemeRegistry, mode: 'light' | 'dark', preset?: FloeThemePreset): string;
@@ -0,0 +1,23 @@
1
+ function l(n, o) {
2
+ const i = o?.monaco?.[n];
3
+ return i ? {
4
+ name: `floe-shell-${n}-${o.name}`,
5
+ definition: i
6
+ } : { name: n === "dark" ? "vs-dark" : "vs" };
7
+ }
8
+ function r(n, o, i) {
9
+ const e = l(o, i);
10
+ if (e.definition) {
11
+ const a = {
12
+ ...e.definition,
13
+ rules: e.definition.rules.map((t) => ({ ...t })),
14
+ colors: { ...e.definition.colors }
15
+ };
16
+ n.defineTheme(e.name, a);
17
+ }
18
+ return n.setTheme(e.name), e.name;
19
+ }
20
+ export {
21
+ r as applyFloeMonacoTheme,
22
+ l as resolveFloeMonacoTheme
23
+ };
@@ -79,6 +79,12 @@ export interface FloeThemeConfig {
79
79
  defaultPreset?: string;
80
80
  /** Optional named token presets for switching visual palettes without changing light/dark mode. */
81
81
  presets?: readonly FloeThemePreset[];
82
+ /** Optional shell-wide presets. Kept separate from product-scoped presets such as chart palettes. */
83
+ shellPresets?: readonly FloeThemePreset[];
84
+ /** Optional per-mode defaults for shell presets. Falls back to the first compatible preset. */
85
+ defaultShellPreset?: Partial<Record<'light' | 'dark', string>>;
86
+ /** Storage key for the versioned per-mode shell preset selection map. */
87
+ shellPresetStorageKey?: string;
82
88
  /**
83
89
  * Optional CSS variable overrides applied at the document root.
84
90
  * `shared` applies to both themes, while `light` / `dark` only apply
@@ -1,5 +1,5 @@
1
1
  import { type Accessor } from 'solid-js';
2
- import { type FloeThemePreset, type ThemeType } from '../styles/themes';
2
+ import { type FloeShellThemeMode, type FloeThemePreset, type ThemeType } from '../styles/themes';
3
3
  export interface ThemeContextValue {
4
4
  theme: Accessor<ThemeType>;
5
5
  resolvedTheme: Accessor<'light' | 'dark'>;
@@ -8,6 +8,11 @@ export interface ThemeContextValue {
8
8
  themePresets: Accessor<readonly FloeThemePreset[]>;
9
9
  themePreset: Accessor<FloeThemePreset | undefined>;
10
10
  setThemePreset: (presetName: string | undefined) => void;
11
+ shellPresets: Accessor<readonly FloeThemePreset[]>;
12
+ shellPreset: Accessor<FloeThemePreset | undefined>;
13
+ shellPresetForMode: (mode: FloeShellThemeMode) => FloeThemePreset | undefined;
14
+ setShellPreset: (presetName: string) => void;
15
+ selectShellTheme: (mode: FloeShellThemeMode, presetName: string) => void;
11
16
  }
12
17
  export declare function createThemeService(): ThemeContextValue;
13
18
  export declare const ThemeProvider: (props: {
@@ -1,69 +1,100 @@
1
- import { createSignal as g, createMemo as E, createEffect as p, onCleanup as P } from "solid-js";
2
- import { createSimpleContext as N } from "./createSimpleContext.js";
3
- import { useResolvedFloeConfig as L } from "./FloeConfigContext.js";
4
- import { getSystemTheme as M, applyTheme as F, syncThemeTokenOverrides as y, resolveThemeTokens as O } from "../styles/themes/index.js";
5
- function i(t, n, r) {
6
- if (n.length !== 0)
7
- return t && n.some((m) => m.name === t) ? t : r && n.some((m) => m.name === r) ? r : n[0]?.name;
1
+ import { createSignal as u, createMemo as L, createEffect as P, onCleanup as $ } from "solid-js";
2
+ import { createSimpleContext as I } from "./createSimpleContext.js";
3
+ import { useResolvedFloeConfig as J } from "./FloeConfigContext.js";
4
+ import { isThemeType as U, getSystemTheme as W, applyTheme as X, applyShellThemeAttribute as z, syncThemeTokenOverrides as A, resolveThemeTokens as Y } from "../styles/themes/index.js";
5
+ import { normalizeShellThemeSelection as O, presetSupportsMode as Q } from "../styles/themes/presets.js";
6
+ function a(s, r, c) {
7
+ if (r.length !== 0)
8
+ return s && r.some((i) => i.name === s) ? s : c && r.some((i) => i.name === c) ? c : r[0]?.name;
8
9
  }
9
- function Q() {
10
- const t = L(), n = () => t.config.theme.storageKey, r = () => t.config.theme.defaultTheme, m = () => t.config.theme.tokens, s = () => t.config.theme.presets ?? [], a = () => t.config.theme.presetStorageKey ?? `${n()}-preset`, c = () => i(t.config.theme.defaultPreset, s()), S = t.persist.load(n(), r()), [d, k] = g(S), x = t.persist.load(a(), c()), [f, l] = g(i(x, s(), c())), [C, K] = g(M());
11
- let h = [];
12
- const T = E(() => {
13
- const e = i(f(), s(), c());
10
+ function Z() {
11
+ const s = J(), r = () => s.config.theme.storageKey, c = () => s.config.theme.defaultTheme, i = () => s.config.theme.tokens, o = () => s.config.theme.presets ?? [], g = () => s.config.theme.presetStorageKey ?? `${r()}-preset`, m = () => a(s.config.theme.defaultPreset, o()), l = () => s.config.theme.shellPresets ?? [], y = () => s.config.theme.shellPresetStorageKey ?? `${r()}-shell-preset`, k = () => s.config.theme.defaultShellPreset ?? {}, x = s.persist.load(r(), c()), R = U(x) ? x : c(), [T, V] = u(R), j = s.persist.load(g(), m()), [S, K] = u(a(j, o(), m())), q = s.persist.load(y(), void 0), [p, C] = u(O(q, l(), k())), [B, D] = u(W());
12
+ let d = [];
13
+ const M = L(() => {
14
+ const e = a(S(), o(), m());
14
15
  if (e)
15
- return s().find((o) => o.name === e);
16
- }), u = () => {
17
- const e = d();
18
- return e === "system" ? C() : e;
19
- };
20
- if (p(() => {
21
- const e = i(f(), s(), c());
22
- f() !== e && l(e);
16
+ return o().find((t) => t.name === e);
17
+ }), h = () => {
18
+ const e = T();
19
+ return e === "system" ? B() : e;
20
+ }, w = (e) => {
21
+ const t = p()[e];
22
+ if (t)
23
+ return l().find((n) => n.name === t && Q(n, e));
24
+ }, E = L(() => w(h()));
25
+ if (P(() => {
26
+ const e = a(S(), o(), m());
27
+ S() !== e && K(e);
28
+ }), P(() => {
29
+ const e = p(), t = O(e, l(), k());
30
+ (e.light !== t.light || e.dark !== t.dark) && C(t);
23
31
  }), typeof window < "u") {
24
- const e = window.matchMedia("(prefers-color-scheme: dark)"), o = (w) => {
25
- K(w.matches ? "dark" : "light");
32
+ const e = window.matchMedia("(prefers-color-scheme: dark)"), t = (n) => {
33
+ D(n.matches ? "dark" : "light");
26
34
  };
27
- e.addEventListener("change", o), P(() => e.removeEventListener("change", o));
35
+ e.addEventListener("change", t), $(() => e.removeEventListener("change", t));
28
36
  }
29
- p(() => {
30
- const e = d(), o = u();
31
- F(e), h = y(O(o, m(), T()?.tokens), h);
32
- }), P(() => {
33
- h = y(void 0, h);
37
+ P(() => {
38
+ const e = T(), t = h(), n = E();
39
+ X(e), z(n?.name), d = A(Y(t, i(), n?.tokens, M()?.tokens), d);
40
+ }), $(() => {
41
+ z(void 0), d = A(void 0, d);
34
42
  });
35
43
  const v = (e) => {
36
- k(e), t.persist.debouncedSave(n(), e);
44
+ V(e), s.persist.debouncedSave(r(), e);
45
+ }, G = () => {
46
+ const e = h();
47
+ v(e === "light" ? "dark" : "light");
48
+ }, H = (e) => {
49
+ const t = a(e, o(), m());
50
+ if (K(t), !t) {
51
+ s.persist.remove(g());
52
+ return;
53
+ }
54
+ s.persist.debouncedSave(g(), t);
55
+ }, N = (e, t) => {
56
+ const n = l().find((F) => F.name === t && Q(F, e));
57
+ if (!n) return !1;
58
+ const f = p();
59
+ if (f[e] === n.name) return !0;
60
+ const b = {
61
+ ...f,
62
+ version: 1,
63
+ [e]: n.name
64
+ };
65
+ return C(b), s.persist.debouncedSave(y(), b), !0;
37
66
  };
38
67
  return {
39
- theme: d,
40
- resolvedTheme: u,
68
+ theme: T,
69
+ resolvedTheme: h,
41
70
  setTheme: v,
42
- toggleTheme: () => {
43
- const e = u();
44
- v(e === "light" ? "dark" : "light");
71
+ toggleTheme: G,
72
+ themePresets: o,
73
+ themePreset: M,
74
+ setThemePreset: H,
75
+ shellPresets: l,
76
+ shellPreset: E,
77
+ shellPresetForMode: w,
78
+ setShellPreset: (e) => {
79
+ const t = l().find((f) => f.name === e);
80
+ if (!t) return;
81
+ const n = t.mode === "light" || t.mode === "dark" ? t.mode : h();
82
+ N(n, e);
45
83
  },
46
- themePresets: s,
47
- themePreset: T,
48
- setThemePreset: (e) => {
49
- const o = i(e, s(), c());
50
- if (l(o), !o) {
51
- t.persist.remove(a());
52
- return;
53
- }
54
- t.persist.debouncedSave(a(), o);
84
+ selectShellTheme: (e, t) => {
85
+ N(e, t) && v(e);
55
86
  }
56
87
  };
57
88
  }
58
89
  const {
59
- Provider: A,
60
- use: B
61
- } = N({
90
+ Provider: ce,
91
+ use: le
92
+ } = I({
62
93
  name: "Theme",
63
- init: Q
94
+ init: Z
64
95
  });
65
96
  export {
66
- A as ThemeProvider,
67
- Q as createThemeService,
68
- B as useTheme
97
+ ce as ThemeProvider,
98
+ Z as createThemeService,
99
+ le as useTheme
69
100
  };
package/dist/editor.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import { CodeEditor as r } from "./components/editor/CodeEditor.js";
2
- import { DEFAULT_MONACO_RUNTIME_PROFILE as E, DEFAULT_MONACO_STANDALONE_FEATURES as a, MONACO_RUNTIME_BLUEPRINTS as i, normalizeMonacoRuntimeFeatureSet as n, resolveMonacoRuntimeProfile as R, resolveMonacoRuntimeRequest as u } from "./components/editor/monacoStandaloneRuntime.js";
3
- import { isCodeEditorLanguageSupported as M, resolveCodeEditorLanguageSpec as N } from "./components/editor/languages.js";
2
+ import { DEFAULT_MONACO_RUNTIME_PROFILE as a, DEFAULT_MONACO_STANDALONE_FEATURES as E, MONACO_RUNTIME_BLUEPRINTS as n, normalizeMonacoRuntimeFeatureSet as m, resolveMonacoRuntimeProfile as M, resolveMonacoRuntimeRequest as i } from "./components/editor/monacoStandaloneRuntime.js";
3
+ import { applyFloeMonacoTheme as p, resolveFloeMonacoTheme as R } from "./components/editor/monacoTheme.js";
4
+ import { isCodeEditorLanguageSupported as u, resolveCodeEditorLanguageSpec as A } from "./components/editor/languages.js";
4
5
  export {
5
6
  r as CodeEditor,
6
- E as DEFAULT_MONACO_RUNTIME_PROFILE,
7
- a as DEFAULT_MONACO_STANDALONE_FEATURES,
8
- i as MONACO_RUNTIME_BLUEPRINTS,
9
- M as isCodeEditorLanguageSupported,
10
- n as normalizeMonacoRuntimeFeatureSet,
11
- N as resolveCodeEditorLanguageSpec,
12
- R as resolveMonacoRuntimeProfile,
13
- u as resolveMonacoRuntimeRequest
7
+ a as DEFAULT_MONACO_RUNTIME_PROFILE,
8
+ E as DEFAULT_MONACO_STANDALONE_FEATURES,
9
+ n as MONACO_RUNTIME_BLUEPRINTS,
10
+ p as applyFloeMonacoTheme,
11
+ u as isCodeEditorLanguageSupported,
12
+ m as normalizeMonacoRuntimeFeatureSet,
13
+ A as resolveCodeEditorLanguageSpec,
14
+ R as resolveFloeMonacoTheme,
15
+ M as resolveMonacoRuntimeProfile,
16
+ i as resolveMonacoRuntimeRequest
14
17
  };
package/dist/floe.css CHANGED
@@ -15,6 +15,7 @@
15
15
  /* Import theme definitions - they define the CSS variables */
16
16
  @import './themes/light.css';
17
17
  @import './themes/dark.css';
18
+ @import './themes/shell-presets.generated.css';
18
19
 
19
20
  :root {
20
21
  --radius: 0.375rem;