@declarion/react 0.1.34 → 0.1.45

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,5 +1,5 @@
1
- export type ThemeId = "light" | "dark" | string;
2
- export type AccentId = "violet" | "blue" | "teal" | "amber" | "rose" | string;
1
+ export type ThemeId = "light" | "dark";
2
+ export type AccentId = "violet" | "blue" | "teal" | "amber" | "rose";
3
3
  export type Density = "compact" | "comfortable" | "cozy";
4
4
  export type SidebarMode = "wide" | "collapsed";
5
5
  export type TabsPosition = "top" | "bottom";
@@ -21,6 +21,10 @@ export declare function applyAppearance(a: Appearance): void;
21
21
  interface AppearanceState extends Appearance {
22
22
  set: <K extends keyof Appearance>(key: K, value: Appearance[K]) => void;
23
23
  setMany: (patch: Partial<Appearance>) => void;
24
+ /** Apply tenant defaults from server params. ONLY fills keys the user has
25
+ * not already set locally — any field present in localStorage wins.
26
+ * That preserves the user's Tweaks choices across reloads while still
27
+ * picking up tenant defaults on first visit. */
24
28
  hydrateFromParams: (params: Record<string, unknown>) => void;
25
29
  }
26
30
  export declare const useAppearanceStore: import("zustand").UseBoundStore<import("zustand").StoreApi<AppearanceState>>;
@@ -1,4 +1,4 @@
1
- import type { AccentDef, LocalizedString, ThemeDef } from "./schema";
1
+ import type { AccentDef, LocalizedString } from "./schema";
2
2
  export interface ListMeta {
3
3
  total: number;
4
4
  page: number;
@@ -27,7 +27,9 @@ export declare class ApiError extends Error {
27
27
  code: string;
28
28
  /** Bulk operation item index (present on validation errors for array requests). */
29
29
  index?: number;
30
- constructor(status: number, message: string, code: string, index?: number);
30
+ /** Raw JSON body for endpoints that return a non-standard error envelope (e.g. invoke:each batch). */
31
+ raw?: unknown;
32
+ constructor(status: number, message: string, code: string, index?: number, raw?: unknown);
31
33
  }
32
34
  export type TenantEnv = "production" | "staging" | "dev" | string;
33
35
  export interface Tenant {
@@ -94,7 +96,6 @@ export interface PublicBranding {
94
96
  /** Envelope returned by GET /api/params/public. */
95
97
  export interface PublicParamsResponse {
96
98
  parameters: PublicParam[];
97
- themes?: Record<string, ThemeDef>;
98
99
  accents?: Record<string, AccentDef>;
99
100
  branding?: PublicBranding;
100
101
  }
@@ -202,11 +202,18 @@ export declare function extractPkValues(entity: Entity, record: Record<string, u
202
202
  export declare function pkValuesToId(pkValues: PkValues): string;
203
203
  export declare function isCompositePk(entity: Entity): boolean;
204
204
  export type SizeValue = string;
205
+ export interface SectionBadgeConfig {
206
+ text: LocalizedString;
207
+ tone?: "indigo" | "emerald" | "amber" | "rose" | "sky" | "violet" | "slate" | "teal";
208
+ dot?: boolean;
209
+ }
205
210
  export interface SectionNode {
206
211
  name: LocalizedString;
207
212
  items: LayoutNode[];
208
213
  collapsed?: boolean;
209
214
  columns?: number;
215
+ icon?: string;
216
+ badge?: SectionBadgeConfig;
210
217
  }
211
218
  export interface RowConfig {
212
219
  items: LayoutNode[];
@@ -426,8 +433,10 @@ export interface Action {
426
433
  primary?: boolean;
427
434
  /** Forces confirm + danger styling. */
428
435
  destructive?: boolean;
429
- /** UI shows toast + Jobs link instead of result modal. */
436
+ /** UI shows a toast instead of a blocking result modal; adds a navigation link if progress_screen is set. */
430
437
  long_running?: boolean;
438
+ /** Screen code to navigate to after a long_running action starts (resolved via schema.screens). */
439
+ progress_screen?: string;
431
440
  /** When true, action shown grayed until >=1 row selected. */
432
441
  bulk_selection_required?: boolean;
433
442
  resolved_params?: OrderedMap<HandlerParam>;
@@ -466,69 +475,7 @@ export interface Branding {
466
475
  auth_tagline?: LocalizedString;
467
476
  auth_subtagline?: LocalizedString;
468
477
  auth_badges?: LocalizedString[];
469
- }
470
- export interface ThemeDef {
471
- extends?: string;
472
- background?: string;
473
- foreground?: string;
474
- card?: string;
475
- card_foreground?: string;
476
- popover?: string;
477
- popover_foreground?: string;
478
- primary?: string;
479
- primary_foreground?: string;
480
- secondary?: string;
481
- secondary_foreground?: string;
482
- muted?: string;
483
- muted_foreground?: string;
484
- accent?: string;
485
- accent_foreground?: string;
486
- destructive?: string;
487
- destructive_foreground?: string;
488
- border?: string;
489
- input?: string;
490
- ring?: string;
491
- sidebar?: string;
492
- sidebar_foreground?: string;
493
- sidebar_border?: string;
494
- sidebar_accent?: string;
495
- sidebar_muted?: string;
496
- radius?: string;
497
- surface?: string;
498
- surface_2?: string;
499
- surface_3?: string;
500
- border_strong?: string;
501
- divider?: string;
502
- text_2?: string;
503
- text_3?: string;
504
- text_4?: string;
505
- text_placeholder?: string;
506
- rail?: string;
507
- rail_fg?: string;
508
- rail_muted?: string;
509
- rail_active?: string;
510
- rail_hover?: string;
511
- sidebar_hover?: string;
512
- sidebar_active?: string;
513
- pills?: Record<string, {
514
- fg: string;
515
- bg: string;
516
- }>;
517
- success_soft?: string;
518
- warn_soft?: string;
519
- danger_soft?: string;
520
- info_soft?: string;
521
- shadow_xs?: string;
522
- shadow_sm?: string;
523
- shadow_md?: string;
524
- shadow_lg?: string;
525
- font_sans?: string;
526
- font_mono?: string;
527
- env_tones?: Record<string, {
528
- fg: string;
529
- bg: string;
530
- border?: string;
531
- }>;
478
+ css_url?: string;
532
479
  }
533
480
  export interface Schema {
534
481
  languages: LanguageDef[];
@@ -541,7 +488,6 @@ export interface Schema {
541
488
  enums: Record<string, EnumDef>;
542
489
  parameters: Record<string, ParameterDef>;
543
490
  branding?: Branding;
544
- themes?: Record<string, ThemeDef>;
545
491
  areas?: AreaDef[];
546
492
  accents?: Record<string, AccentDef>;
547
493
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@declarion/react",
3
- "version": "0.1.34",
3
+ "version": "0.1.45",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "React SDK for Declarion, the schema-driven business apps platform.",
@@ -1,71 +0,0 @@
1
- import { jsx as b } from "react/jsx-runtime";
2
- import { useRef as i, useEffect as a } from "react";
3
- import { Mode as d, createJSONEditor as E } from "vanilla-jsoneditor";
4
- import "vanilla-jsoneditor/themes/jse-theme-dark.css";
5
- function p(t) {
6
- if (t == null) return { text: "" };
7
- if (typeof t == "string")
8
- try {
9
- return { json: JSON.parse(t) };
10
- } catch {
11
- return { text: t };
12
- }
13
- return { json: t };
14
- }
15
- function R({ value: t, onChange: c, readOnly: r }) {
16
- const o = i(null), s = i(null), n = i(c);
17
- return a(() => {
18
- n.current = c;
19
- }, [c]), a(() => {
20
- if (!o.current) return;
21
- const j = {
22
- content: p(t),
23
- readOnly: r ?? !1,
24
- mode: r ? d.tree : d.text,
25
- mainMenuBar: !r,
26
- navigationBar: !1,
27
- statusBar: !1,
28
- onChange: (e, u, x) => {
29
- if (!(r || !n.current) && !x.contentErrors) {
30
- if ("json" in e)
31
- n.current(e.json);
32
- else if ("text" in e)
33
- try {
34
- n.current(JSON.parse(e.text));
35
- } catch {
36
- n.current(e.text);
37
- }
38
- }
39
- }
40
- }, f = () => {
41
- var u;
42
- const e = document.documentElement.classList.contains("dark");
43
- (u = o.current) == null || u.classList.toggle("jse-theme-dark", e);
44
- };
45
- f();
46
- const m = new MutationObserver(f);
47
- m.observe(document.documentElement, {
48
- attributes: !0,
49
- attributeFilter: ["class"]
50
- });
51
- const l = E({
52
- target: o.current,
53
- props: j
54
- });
55
- return s.current = l, () => {
56
- m.disconnect(), l.destroy(), s.current = null;
57
- };
58
- }, [r]), a(() => {
59
- !s.current || !r || s.current.updateProps({ content: p(t) });
60
- }, [t, r]), /* @__PURE__ */ b(
61
- "div",
62
- {
63
- ref: o,
64
- className: r ? "json-editor-readonly" : "json-editor-editable"
65
- }
66
- );
67
- }
68
- export {
69
- R as JsonEditor
70
- };
71
- //# sourceMappingURL=JsonEditor-C5NOzsey.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"JsonEditor-C5NOzsey.js","sources":["../src/components/fields/JsonEditor.tsx"],"sourcesContent":["import { useRef, useEffect } from \"react\";\nimport {\n createJSONEditor,\n Mode,\n type Content,\n type OnChangeStatus,\n type JSONEditorPropsOptional,\n} from \"vanilla-jsoneditor\";\n// Dark theme CSS vars for vanilla-jsoneditor (sets --jse-* custom properties)\nimport \"vanilla-jsoneditor/themes/jse-theme-dark.css\";\n\ninterface JsonEditorProps {\n value: unknown;\n onChange?: (value: unknown) => void;\n readOnly?: boolean;\n // Future: JSON Schema for in-editor validation (Ajv). Accept now, wire later.\n schema?: Record<string, unknown>;\n}\n\nfunction toContent(v: unknown): Content {\n if (v == null) return { text: \"\" };\n if (typeof v === \"string\") {\n try {\n return { json: JSON.parse(v) };\n } catch {\n return { text: v };\n }\n }\n return { json: v };\n}\n\nexport function JsonEditor({ value, onChange, readOnly }: JsonEditorProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const editorRef = useRef<ReturnType<typeof createJSONEditor> | null>(null);\n const onChangeRef = useRef(onChange);\n useEffect(() => { onChangeRef.current = onChange; }, [onChange]);\n\n // Create / recreate editor when readOnly changes\n useEffect(() => {\n if (!containerRef.current) return;\n\n const props: JSONEditorPropsOptional = {\n content: toContent(value),\n readOnly: readOnly ?? false,\n mode: readOnly ? Mode.tree : Mode.text,\n mainMenuBar: !readOnly,\n navigationBar: false,\n statusBar: false,\n onChange: (content: Content, _prev: Content, status: OnChangeStatus) => {\n if (readOnly || !onChangeRef.current) return;\n if (status.contentErrors) return;\n if (\"json\" in content) {\n onChangeRef.current(content.json);\n } else if (\"text\" in content) {\n try {\n onChangeRef.current(JSON.parse(content.text));\n } catch {\n onChangeRef.current(content.text);\n }\n }\n },\n };\n\n const syncDarkClass = () => {\n const isDark = document.documentElement.classList.contains(\"dark\");\n containerRef.current?.classList.toggle(\"jse-theme-dark\", isDark);\n };\n syncDarkClass();\n\n // Watch for dark mode toggles\n const observer = new MutationObserver(syncDarkClass);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"class\"],\n });\n\n const editor = createJSONEditor({\n target: containerRef.current,\n props,\n });\n editorRef.current = editor;\n\n return () => {\n observer.disconnect();\n editor.destroy();\n editorRef.current = null;\n };\n }, [readOnly]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Update content when value changes externally (read-only mode only)\n useEffect(() => {\n if (!editorRef.current || !readOnly) return;\n editorRef.current.updateProps({ content: toContent(value) });\n }, [value, readOnly]);\n\n return (\n <div\n ref={containerRef}\n className={readOnly ? \"json-editor-readonly\" : \"json-editor-editable\"}\n />\n );\n}\n"],"names":["toContent","v","JsonEditor","value","onChange","readOnly","containerRef","useRef","editorRef","onChangeRef","useEffect","props","Mode","content","_prev","status","syncDarkClass","isDark","_a","observer","editor","createJSONEditor","jsx"],"mappings":";;;;AAmBA,SAASA,EAAUC,GAAqB;AACtC,MAAIA,KAAK,KAAM,QAAO,EAAE,MAAM,GAAA;AAC9B,MAAI,OAAOA,KAAM;AACf,QAAI;AACF,aAAO,EAAE,MAAM,KAAK,MAAMA,CAAC,EAAA;AAAA,IAC7B,QAAQ;AACN,aAAO,EAAE,MAAMA,EAAA;AAAA,IACjB;AAEF,SAAO,EAAE,MAAMA,EAAA;AACjB;AAEO,SAASC,EAAW,EAAE,OAAAC,GAAO,UAAAC,GAAU,UAAAC,KAA6B;AACzE,QAAMC,IAAeC,EAAuB,IAAI,GAC1CC,IAAYD,EAAmD,IAAI,GACnEE,IAAcF,EAAOH,CAAQ;AACnC,SAAAM,EAAU,MAAM;AAAE,IAAAD,EAAY,UAAUL;AAAA,EAAU,GAAG,CAACA,CAAQ,CAAC,GAG/DM,EAAU,MAAM;AACd,QAAI,CAACJ,EAAa,QAAS;AAE3B,UAAMK,IAAiC;AAAA,MACrC,SAASX,EAAUG,CAAK;AAAA,MACxB,UAAUE,KAAY;AAAA,MACtB,MAAMA,IAAWO,EAAK,OAAOA,EAAK;AAAA,MAClC,aAAa,CAACP;AAAA,MACd,eAAe;AAAA,MACf,WAAW;AAAA,MACX,UAAU,CAACQ,GAAkBC,GAAgBC,MAA2B;AACtE,YAAI,EAAAV,KAAY,CAACI,EAAY,YACzB,CAAAM,EAAO;AACX,cAAI,UAAUF;AACZ,YAAAJ,EAAY,QAAQI,EAAQ,IAAI;AAAA,mBACvB,UAAUA;AACnB,gBAAI;AACF,cAAAJ,EAAY,QAAQ,KAAK,MAAMI,EAAQ,IAAI,CAAC;AAAA,YAC9C,QAAQ;AACN,cAAAJ,EAAY,QAAQI,EAAQ,IAAI;AAAA,YAClC;AAAA;AAAA,MAEJ;AAAA,IAAA,GAGIG,IAAgB,MAAM;;AAC1B,YAAMC,IAAS,SAAS,gBAAgB,UAAU,SAAS,MAAM;AACjE,OAAAC,IAAAZ,EAAa,YAAb,QAAAY,EAAsB,UAAU,OAAO,kBAAkBD;AAAA,IAC3D;AACA,IAAAD,EAAA;AAGA,UAAMG,IAAW,IAAI,iBAAiBH,CAAa;AACnD,IAAAG,EAAS,QAAQ,SAAS,iBAAiB;AAAA,MACzC,YAAY;AAAA,MACZ,iBAAiB,CAAC,OAAO;AAAA,IAAA,CAC1B;AAED,UAAMC,IAASC,EAAiB;AAAA,MAC9B,QAAQf,EAAa;AAAA,MACrB,OAAAK;AAAA,IAAA,CACD;AACD,WAAAH,EAAU,UAAUY,GAEb,MAAM;AACX,MAAAD,EAAS,WAAA,GACTC,EAAO,QAAA,GACPZ,EAAU,UAAU;AAAA,IACtB;AAAA,EACF,GAAG,CAACH,CAAQ,CAAC,GAGbK,EAAU,MAAM;AACd,IAAI,CAACF,EAAU,WAAW,CAACH,KAC3BG,EAAU,QAAQ,YAAY,EAAE,SAASR,EAAUG,CAAK,GAAG;AAAA,EAC7D,GAAG,CAACA,GAAOE,CAAQ,CAAC,GAGlB,gBAAAiB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKhB;AAAA,MACL,WAAWD,IAAW,yBAAyB;AAAA,IAAA;AAAA,EAAA;AAGrD;"}
@@ -1,3 +0,0 @@
1
- import type { ThemeDef } from "../types/schema";
2
- export declare const THEME_TOKENS: string[];
3
- export declare function themeDefToTokens(def: ThemeDef): Record<string, string>;
@@ -1,10 +0,0 @@
1
- type ThemeTokens = Record<string, string>;
2
- interface ThemeState {
3
- selectedTheme: string;
4
- effectiveTheme: string;
5
- availableThemes: Record<string, ThemeTokens>;
6
- setTheme: (name: string) => void;
7
- setAvailableThemes: (themes: Record<string, ThemeTokens>) => void;
8
- }
9
- export declare const useThemeStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ThemeState>>;
10
- export {};