@solidxai/core-ui 0.1.7 → 0.1.8-beta.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.
@@ -1 +1 @@
1
- {"version":3,"file":"SolidLayoutRegistry.d.ts","sourceRoot":"","sources":["../../src/routes/SolidLayoutRegistry.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAOD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAErE;AA+ED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAOA;AAID;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,EAAE,CAI3D"}
1
+ {"version":3,"file":"SolidLayoutRegistry.d.ts","sourceRoot":"","sources":["../../src/routes/SolidLayoutRegistry.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAOD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAErE;AAoHD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAOA;AAMD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,EAAE,CAI3D"}
@@ -64,22 +64,54 @@ function resolveFirstChildTo(basePath, children) {
64
64
  return concretePath;
65
65
  return "".concat(basePath.replace(/\/$/, ""), "/").concat(concretePath);
66
66
  }
67
+ function inferPathFromChildren(children) {
68
+ var _a, _b;
69
+ for (var _i = 0, children_3 = children; _i < children_3.length; _i++) {
70
+ var child = children_3[_i];
71
+ // Absolute path → use root
72
+ if ((_a = child.path) === null || _a === void 0 ? void 0 : _a.startsWith("/")) {
73
+ var root = child.path.split("/").filter(Boolean)[0];
74
+ return root ? "/".concat(root) : undefined;
75
+ }
76
+ // Relative path → use first segment
77
+ if (child.path) {
78
+ var root = child.path.split("/")[0];
79
+ return root ? "/".concat(root) : undefined;
80
+ }
81
+ // Nested
82
+ if ((_b = child.children) === null || _b === void 0 ? void 0 : _b.length) {
83
+ var nested = inferPathFromChildren(child.children);
84
+ if (nested)
85
+ return nested;
86
+ }
87
+ }
88
+ return undefined;
89
+ }
67
90
  function extractLayouts(routes) {
68
- return routes
69
- .filter(function (r) { return !!r.path; })
70
- .map(function (r) {
71
- var _a, _b;
72
- var handle = r.handle;
73
- var to = ((_a = r.children) === null || _a === void 0 ? void 0 : _a.length)
74
- ? resolveFirstChildTo(r.path, r.children)
75
- : r.path; // 👈 fallback for standalone routes
76
- return {
77
- path: r.path,
78
- title: (_b = handle === null || handle === void 0 ? void 0 : handle.title) !== null && _b !== void 0 ? _b : pathToTitle(r.path),
91
+ var _a, _b, _c, _d;
92
+ var layouts = [];
93
+ var seen = new Set();
94
+ for (var _i = 0, routes_1 = routes; _i < routes_1.length; _i++) {
95
+ var route = routes_1[_i];
96
+ // Use explicit path OR infer from children
97
+ var basePath = (_a = route.path) !== null && _a !== void 0 ? _a : (((_b = route.children) === null || _b === void 0 ? void 0 : _b.length)
98
+ ? inferPathFromChildren(route.children)
99
+ : undefined);
100
+ if (!basePath || seen.has(basePath))
101
+ continue;
102
+ var handle = route.handle;
103
+ var to = ((_c = route.children) === null || _c === void 0 ? void 0 : _c.length)
104
+ ? resolveFirstChildTo(basePath, route.children)
105
+ : basePath;
106
+ layouts.push({
107
+ path: basePath,
108
+ title: (_d = handle === null || handle === void 0 ? void 0 : handle.title) !== null && _d !== void 0 ? _d : pathToTitle(basePath),
79
109
  description: handle === null || handle === void 0 ? void 0 : handle.description,
80
110
  to: to,
81
- };
82
- });
111
+ });
112
+ seen.add(basePath);
113
+ }
114
+ return layouts;
83
115
  }
84
116
  // ── Provider (optional override) ──────────────────────────────────────────────
85
117
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"SolidLayoutRegistry.js","sourceRoot":"","sources":["../../src/routes/SolidLayoutRegistry.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { RouteObject } from \"react-router-dom\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface SolidLayoutEntry {\n /** The root path of this layout, e.g. \"/jenendar\" */\n path: string;\n /** Display title. Falls back to title-casing the path segment. */\n title: string;\n /** Optional subtitle shown on the card. */\n description?: string;\n /** Resolved URL to navigate to when the card is clicked (first child). */\n to: string;\n}\n\n/**\n * Optionally attach this to a route's `handle` to customise the card.\n *\n * @example\n * ```tsx\n * {\n * path: \"/my-layout\",\n * handle: { title: \"My Layout\", description: \"Custom layout\" } satisfies SolidLayoutHandle,\n * element: <MyLayout />,\n * children: [...],\n * }\n * ```\n */\nexport interface SolidLayoutHandle {\n title?: string;\n description?: string;\n}\n\n// ── Module-level store ────────────────────────────────────────────────────────\n// Populated automatically inside getSolidRoutes() — no consumer changes needed.\n\nlet _autoRoutes: RouteObject[] = [];\n\n/**\n * Called by getSolidRoutes() whenever extraRoutes are provided.\n * @internal — not part of the public API.\n */\nexport function _solidRegisterExtraRoutes(routes: RouteObject[]): void {\n _autoRoutes = routes;\n}\n\n// ── Context (optional override) ───────────────────────────────────────────────\n// Mount SolidLayoutRegistryProvider anywhere above StudioLandingPage to\n// override the auto-registered list (e.g. async / runtime route lists).\n\nconst SolidLayoutRegistryContext = createContext<SolidLayoutEntry[] | null>(null);\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction pathToTitle(path: string): string {\n return (\n path\n .replace(/^\\//, \"\")\n .split(/[-_/]/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \") || path\n );\n}\n\n/**\n * Walk a route tree and return the first concrete relative or absolute path found.\n * Skips index routes (they render at the parent path) and pathless wrappers\n * (guards, layout wrappers) by looking inside their children recursively.\n */\nfunction findFirstConcretePath(children: RouteObject[]): string | undefined {\n // 1. FIRST PASS → prioritize index (including inside pathless wrappers)\n for (const child of children) {\n if ((child as any).index || child.path === \"\") {\n return \"\";\n }\n // Deep check for pathless wrappers in the first pass too\n if (!child.path && child.children?.length) {\n const nested = findFirstConcretePath(child.children);\n if (nested === \"\") return \"\";\n }\n }\n\n // 2. SECOND PASS → find first path\n for (const child of children) {\n if (child.path) return child.path;\n\n if (child.children?.length) {\n const nested = findFirstConcretePath(child.children);\n if (nested !== undefined) return nested;\n }\n }\n\n return undefined;\n}\nfunction resolveFirstChildTo(basePath: string, children: RouteObject[]): string {\n const concretePath = findFirstConcretePath(children);\n if (concretePath === undefined || concretePath === \"\") return basePath;\n if (concretePath.startsWith(\"/\")) return concretePath;\n return `${basePath.replace(/\\/$/, \"\")}/${concretePath}`;\n}\n\nfunction extractLayouts(routes: RouteObject[]): SolidLayoutEntry[] {\n return routes\n .filter((r) => !!r.path)\n .map((r) => {\n const handle = r.handle as SolidLayoutHandle | undefined;\n\n const to = r.children?.length\n ? resolveFirstChildTo(r.path!, r.children)\n : r.path!; // 👈 fallback for standalone routes\n\n return {\n path: r.path!,\n title: handle?.title ?? pathToTitle(r.path!),\n description: handle?.description,\n to,\n };\n });\n}\n\n// ── Provider (optional override) ──────────────────────────────────────────────\n\n/**\n * Optional — most apps do NOT need this.\n * Use only when you need to override the auto-registered list at runtime.\n */\nexport function SolidLayoutRegistryProvider({\n routes,\n children,\n}: {\n routes: RouteObject[];\n children: ReactNode;\n}) {\n const layouts = useMemo(() => extractLayouts(routes), [routes]);\n return (\n <SolidLayoutRegistryContext.Provider value={layouts}>\n {children}\n </SolidLayoutRegistryContext.Provider>\n );\n}\n\n// ── Hook ──────────────────────────────────────────────────────────────────────\n\n/**\n * Returns the registered layout entries.\n *\n * Priority order:\n * 1. SolidLayoutRegistryProvider context (if mounted)\n * 2. Routes auto-registered when getSolidRoutes({ extraRoutes }) was called\n */\nexport function useSolidLayoutRegistry(): SolidLayoutEntry[] {\n const contextLayouts = useContext(SolidLayoutRegistryContext);\n if (contextLayouts !== null) return contextLayouts;\n return extractLayouts(_autoRoutes);\n}\n"]}
1
+ {"version":3,"file":"SolidLayoutRegistry.js","sourceRoot":"","sources":["../../src/routes/SolidLayoutRegistry.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { RouteObject } from \"react-router-dom\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface SolidLayoutEntry {\n /** The root path of this layout, e.g. \"/jenendar\" */\n path: string;\n /** Display title. Falls back to title-casing the path segment. */\n title: string;\n /** Optional subtitle shown on the card. */\n description?: string;\n /** Resolved URL to navigate to when the card is clicked (first child). */\n to: string;\n}\n\n/**\n * Optionally attach this to a route's `handle` to customise the card.\n *\n * @example\n * ```tsx\n * {\n * path: \"/my-layout\",\n * handle: { title: \"My Layout\", description: \"Custom layout\" } satisfies SolidLayoutHandle,\n * element: <MyLayout />,\n * children: [...],\n * }\n * ```\n */\nexport interface SolidLayoutHandle {\n title?: string;\n description?: string;\n}\n\n// ── Module-level store ────────────────────────────────────────────────────────\n// Populated automatically inside getSolidRoutes() — no consumer changes needed.\n\nlet _autoRoutes: RouteObject[] = [];\n\n/**\n * Called by getSolidRoutes() whenever extraRoutes are provided.\n * @internal — not part of the public API.\n */\nexport function _solidRegisterExtraRoutes(routes: RouteObject[]): void {\n _autoRoutes = routes;\n}\n\n// ── Context (optional override) ───────────────────────────────────────────────\n// Mount SolidLayoutRegistryProvider anywhere above StudioLandingPage to\n// override the auto-registered list (e.g. async / runtime route lists).\n\nconst SolidLayoutRegistryContext = createContext<SolidLayoutEntry[] | null>(null);\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction pathToTitle(path: string): string {\n return (\n path\n .replace(/^\\//, \"\")\n .split(/[-_/]/)\n .filter(Boolean)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \") || path\n );\n}\n\n/**\n * Walk a route tree and return the first concrete relative or absolute path found.\n * Skips index routes (they render at the parent path) and pathless wrappers\n * (guards, layout wrappers) by looking inside their children recursively.\n */\nfunction findFirstConcretePath(children: RouteObject[]): string | undefined {\n // 1. FIRST PASS → prioritize index (including inside pathless wrappers)\n for (const child of children) {\n if ((child as any).index || child.path === \"\") {\n return \"\";\n }\n // Deep check for pathless wrappers in the first pass too\n if (!child.path && child.children?.length) {\n const nested = findFirstConcretePath(child.children);\n if (nested === \"\") return \"\";\n }\n }\n\n // 2. SECOND PASS → find first path\n for (const child of children) {\n if (child.path) return child.path;\n\n if (child.children?.length) {\n const nested = findFirstConcretePath(child.children);\n if (nested !== undefined) return nested;\n }\n }\n\n return undefined;\n}\nfunction resolveFirstChildTo(basePath: string, children: RouteObject[]): string {\n const concretePath = findFirstConcretePath(children);\n if (concretePath === undefined || concretePath === \"\") return basePath;\n if (concretePath.startsWith(\"/\")) return concretePath;\n return `${basePath.replace(/\\/$/, \"\")}/${concretePath}`;\n}\n\nfunction inferPathFromChildren(children: RouteObject[]): string | undefined {\n for (const child of children) {\n // Absolute path → use root\n if (child.path?.startsWith(\"/\")) {\n const root = child.path.split(\"/\").filter(Boolean)[0];\n return root ? `/${root}` : undefined;\n }\n\n // Relative path → use first segment\n if (child.path) {\n const root = child.path.split(\"/\")[0];\n return root ? `/${root}` : undefined;\n }\n\n // Nested\n if (child.children?.length) {\n const nested = inferPathFromChildren(child.children);\n if (nested) return nested;\n }\n }\n\n return undefined;\n}\n\nfunction extractLayouts(routes: RouteObject[]): SolidLayoutEntry[] {\n const layouts: SolidLayoutEntry[] = [];\n const seen = new Set<string>();\n\n for (const route of routes) {\n // ✅ Use explicit path OR infer from children\n const basePath =\n route.path ??\n (route.children?.length\n ? inferPathFromChildren(route.children)\n : undefined);\n\n if (!basePath || seen.has(basePath)) continue;\n\n const handle = route.handle as SolidLayoutHandle | undefined;\n\n const to = route.children?.length\n ? resolveFirstChildTo(basePath, route.children)\n : basePath;\n\n layouts.push({\n path: basePath,\n title: handle?.title ?? pathToTitle(basePath),\n description: handle?.description,\n to,\n });\n\n seen.add(basePath);\n }\n\n return layouts;\n}\n// ── Provider (optional override) ──────────────────────────────────────────────\n\n/**\n * Optional — most apps do NOT need this.\n * Use only when you need to override the auto-registered list at runtime.\n */\nexport function SolidLayoutRegistryProvider({\n routes,\n children,\n}: {\n routes: RouteObject[];\n children: ReactNode;\n}) {\n const layouts = useMemo(() => extractLayouts(routes), [routes]);\n return (\n <SolidLayoutRegistryContext.Provider value={layouts}>\n {children}\n </SolidLayoutRegistryContext.Provider>\n );\n}\n\n\n\n// ── Hook ──────────────────────────────────────────────────────────────────────\n\n/**\n * Returns the registered layout entries.\n *\n * Priority order:\n * 1. SolidLayoutRegistryProvider context (if mounted)\n * 2. Routes auto-registered when getSolidRoutes({ extraRoutes }) was called\n */\nexport function useSolidLayoutRegistry(): SolidLayoutEntry[] {\n const contextLayouts = useContext(SolidLayoutRegistryContext);\n if (contextLayouts !== null) return contextLayouts;\n return extractLayouts(_autoRoutes);\n}\n"]}
@@ -101,25 +101,62 @@ function resolveFirstChildTo(basePath: string, children: RouteObject[]): string
101
101
  return `${basePath.replace(/\/$/, "")}/${concretePath}`;
102
102
  }
103
103
 
104
+ function inferPathFromChildren(children: RouteObject[]): string | undefined {
105
+ for (const child of children) {
106
+ // Absolute path → use root
107
+ if (child.path?.startsWith("/")) {
108
+ const root = child.path.split("/").filter(Boolean)[0];
109
+ return root ? `/${root}` : undefined;
110
+ }
111
+
112
+ // Relative path → use first segment
113
+ if (child.path) {
114
+ const root = child.path.split("/")[0];
115
+ return root ? `/${root}` : undefined;
116
+ }
117
+
118
+ // Nested
119
+ if (child.children?.length) {
120
+ const nested = inferPathFromChildren(child.children);
121
+ if (nested) return nested;
122
+ }
123
+ }
124
+
125
+ return undefined;
126
+ }
127
+
104
128
  function extractLayouts(routes: RouteObject[]): SolidLayoutEntry[] {
105
- return routes
106
- .filter((r) => !!r.path)
107
- .map((r) => {
108
- const handle = r.handle as SolidLayoutHandle | undefined;
109
-
110
- const to = r.children?.length
111
- ? resolveFirstChildTo(r.path!, r.children)
112
- : r.path!; // 👈 fallback for standalone routes
113
-
114
- return {
115
- path: r.path!,
116
- title: handle?.title ?? pathToTitle(r.path!),
117
- description: handle?.description,
118
- to,
119
- };
129
+ const layouts: SolidLayoutEntry[] = [];
130
+ const seen = new Set<string>();
131
+
132
+ for (const route of routes) {
133
+ // ✅ Use explicit path OR infer from children
134
+ const basePath =
135
+ route.path ??
136
+ (route.children?.length
137
+ ? inferPathFromChildren(route.children)
138
+ : undefined);
139
+
140
+ if (!basePath || seen.has(basePath)) continue;
141
+
142
+ const handle = route.handle as SolidLayoutHandle | undefined;
143
+
144
+ const to = route.children?.length
145
+ ? resolveFirstChildTo(basePath, route.children)
146
+ : basePath;
147
+
148
+ layouts.push({
149
+ path: basePath,
150
+ title: handle?.title ?? pathToTitle(basePath),
151
+ description: handle?.description,
152
+ to,
120
153
  });
121
- }
122
154
 
155
+ seen.add(basePath);
156
+ }
157
+
158
+ return layouts;
159
+ }
123
160
  // ── Provider (optional override) ──────────────────────────────────────────────
124
161
 
125
162
  /**
@@ -141,6 +178,8 @@ export function SolidLayoutRegistryProvider({
141
178
  );
142
179
  }
143
180
 
181
+
182
+
144
183
  // ── Hook ──────────────────────────────────────────────────────────────────────
145
184
 
146
185
  /**
@@ -1,13 +1,13 @@
1
1
  export declare const ExtensionComponentTypes: {
2
- readonly list_field_widget: "list_field_widget";
3
- readonly list_row_action: "list_row_action";
4
- readonly list_header_action: "list_header_action";
5
- readonly form_field_view_widget: "form_field_view_widget";
6
- readonly form_field_edit_widget: "form_field_edit_widget";
7
- readonly form_action: "form_action";
8
- readonly form_widget: "form_widget";
9
- readonly kanban_card_widget: "kanban_card_widget";
10
- readonly card_widget: "card_widget";
2
+ readonly listFieldWidget: "listFieldWidget";
3
+ readonly listRowAction: "listRowAction";
4
+ readonly listHeaderAction: "listHeaderAction";
5
+ readonly formFieldViewWidget: "formFieldViewWidget";
6
+ readonly formFieldEditWidget: "formFieldEditWidget";
7
+ readonly formAction: "formAction";
8
+ readonly formWidget: "formWidget";
9
+ readonly kanbanCardWidget: "kanbanCardWidget";
10
+ readonly cardWidget: "cardWidget";
11
11
  };
12
12
  export type ExtensionComponentType = (typeof ExtensionComponentTypes)[keyof typeof ExtensionComponentTypes];
13
13
  export declare const ExtensionFunctionTypes: {
@@ -1,13 +1,13 @@
1
1
  export var ExtensionComponentTypes = {
2
- list_field_widget: "list_field_widget",
3
- list_row_action: "list_row_action",
4
- list_header_action: "list_header_action",
5
- form_field_view_widget: "form_field_view_widget",
6
- form_field_edit_widget: "form_field_edit_widget",
7
- form_action: "form_action",
8
- form_widget: "form_widget",
9
- kanban_card_widget: "kanban_card_widget",
10
- card_widget: "card_widget",
2
+ listFieldWidget: "listFieldWidget",
3
+ listRowAction: "listRowAction",
4
+ listHeaderAction: "listHeaderAction",
5
+ formFieldViewWidget: "formFieldViewWidget",
6
+ formFieldEditWidget: "formFieldEditWidget",
7
+ formAction: "formAction",
8
+ formWidget: "formWidget",
9
+ kanbanCardWidget: "kanbanCardWidget",
10
+ cardWidget: "cardWidget",
11
11
  };
12
12
  export var ExtensionFunctionTypes = {
13
13
  onFieldChange: "onFieldChange",
@@ -1 +1 @@
1
- {"version":3,"file":"extension-registry.js","sourceRoot":"","sources":["../../src/types/extension-registry.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,uBAAuB,GAAG;IACnC,iBAAiB,EAAE,mBAAmB;IACtC,eAAe,EAAE,iBAAiB;IAClC,kBAAkB,EAAE,oBAAoB;IACxC,sBAAsB,EAAE,wBAAwB;IAChD,sBAAsB,EAAE,wBAAwB;IAChD,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,aAAa;IAC1B,kBAAkB,EAAE,oBAAoB;IACxC,WAAW,EAAE,aAAa;CACpB,CAAC;AAKX,MAAM,CAAC,IAAM,sBAAsB,GAAG;IAClC,aAAa,EAAE,eAAe;IAC9B,WAAW,EAAE,aAAa;IAC1B,cAAc,EAAE,gBAAgB;IAChC,gBAAgB,EAAE,kBAAkB;IACpC,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,sBAAsB;IAC5C,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,sBAAsB;IAC5C,UAAU,EAAE,YAAY;IACxB,YAAY,EAAE,cAAc;IAC5B,kBAAkB,EAAE,oBAAoB;CAClC,CAAC","sourcesContent":["export const ExtensionComponentTypes = {\n list_field_widget: \"list_field_widget\",\n list_row_action: \"list_row_action\",\n list_header_action: \"list_header_action\",\n form_field_view_widget: \"form_field_view_widget\",\n form_field_edit_widget: \"form_field_edit_widget\",\n form_action: \"form_action\",\n form_widget: \"form_widget\",\n kanban_card_widget: \"kanban_card_widget\",\n card_widget: \"card_widget\",\n} as const;\n\nexport type ExtensionComponentType =\n (typeof ExtensionComponentTypes)[keyof typeof ExtensionComponentTypes];\n\nexport const ExtensionFunctionTypes = {\n onFieldChange: \"onFieldChange\",\n onFieldBlur: \"onFieldBlur\",\n onFormDataLoad: \"onFormDataLoad\",\n onFormLayoutLoad: \"onFormLayoutLoad\",\n onFormLoad: \"onFormLoad\",\n onListLoad: \"onListLoad\",\n onBeforeListDataLoad: \"onBeforeListDataLoad\",\n onTreeLoad: \"onTreeLoad\",\n onBeforeTreeDataLoad: \"onBeforeTreeDataLoad\",\n afterLogin: \"afterLogin\",\n beforeLogout: \"beforeLogout\",\n onApplicationMount: \"onApplicationMount\",\n} as const;\n\nexport type ExtensionFunctionType =\n (typeof ExtensionFunctionTypes)[keyof typeof ExtensionFunctionTypes];\n"]}
1
+ {"version":3,"file":"extension-registry.js","sourceRoot":"","sources":["../../src/types/extension-registry.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,uBAAuB,GAAG;IACnC,eAAe,EAAE,iBAAiB;IAClC,aAAa,EAAE,eAAe;IAC9B,gBAAgB,EAAE,kBAAkB;IACpC,mBAAmB,EAAE,qBAAqB;IAC1C,mBAAmB,EAAE,qBAAqB;IAC1C,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,kBAAkB;IACpC,UAAU,EAAE,YAAY;CAClB,CAAC;AAKX,MAAM,CAAC,IAAM,sBAAsB,GAAG;IAClC,aAAa,EAAE,eAAe;IAC9B,WAAW,EAAE,aAAa;IAC1B,cAAc,EAAE,gBAAgB;IAChC,gBAAgB,EAAE,kBAAkB;IACpC,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,sBAAsB;IAC5C,UAAU,EAAE,YAAY;IACxB,oBAAoB,EAAE,sBAAsB;IAC5C,UAAU,EAAE,YAAY;IACxB,YAAY,EAAE,cAAc;IAC5B,kBAAkB,EAAE,oBAAoB;CAClC,CAAC","sourcesContent":["export const ExtensionComponentTypes = {\n listFieldWidget: \"listFieldWidget\",\n listRowAction: \"listRowAction\",\n listHeaderAction: \"listHeaderAction\",\n formFieldViewWidget: \"formFieldViewWidget\",\n formFieldEditWidget: \"formFieldEditWidget\",\n formAction: \"formAction\",\n formWidget: \"formWidget\",\n kanbanCardWidget: \"kanbanCardWidget\",\n cardWidget: \"cardWidget\",\n} as const;\n\nexport type ExtensionComponentType =\n (typeof ExtensionComponentTypes)[keyof typeof ExtensionComponentTypes];\n\nexport const ExtensionFunctionTypes = {\n onFieldChange: \"onFieldChange\",\n onFieldBlur: \"onFieldBlur\",\n onFormDataLoad: \"onFormDataLoad\",\n onFormLayoutLoad: \"onFormLayoutLoad\",\n onFormLoad: \"onFormLoad\",\n onListLoad: \"onListLoad\",\n onBeforeListDataLoad: \"onBeforeListDataLoad\",\n onTreeLoad: \"onTreeLoad\",\n onBeforeTreeDataLoad: \"onBeforeTreeDataLoad\",\n afterLogin: \"afterLogin\",\n beforeLogout: \"beforeLogout\",\n onApplicationMount: \"onApplicationMount\",\n} as const;\n\nexport type ExtensionFunctionType =\n (typeof ExtensionFunctionTypes)[keyof typeof ExtensionFunctionTypes];\n"]}
@@ -1,13 +1,13 @@
1
1
  export const ExtensionComponentTypes = {
2
- list_field_widget: "list_field_widget",
3
- list_row_action: "list_row_action",
4
- list_header_action: "list_header_action",
5
- form_field_view_widget: "form_field_view_widget",
6
- form_field_edit_widget: "form_field_edit_widget",
7
- form_action: "form_action",
8
- form_widget: "form_widget",
9
- kanban_card_widget: "kanban_card_widget",
10
- card_widget: "card_widget",
2
+ listFieldWidget: "listFieldWidget",
3
+ listRowAction: "listRowAction",
4
+ listHeaderAction: "listHeaderAction",
5
+ formFieldViewWidget: "formFieldViewWidget",
6
+ formFieldEditWidget: "formFieldEditWidget",
7
+ formAction: "formAction",
8
+ formWidget: "formWidget",
9
+ kanbanCardWidget: "kanbanCardWidget",
10
+ cardWidget: "cardWidget",
11
11
  } as const;
12
12
 
13
13
  export type ExtensionComponentType =
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidxai/core-ui",
3
- "version": "0.1.7",
3
+ "version": "0.1.8-beta.1",
4
4
  "scripts": {
5
5
  "prebuild": "npm run copy-resources && npm run copy-styles",
6
6
  "build": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "keywords": [],
14
14
  "author": "",
15
- "license": "ISC",
15
+ "license": "BUSL-1.1",
16
16
  "description": "",
17
17
  "main": "dist/index.js",
18
18
  "types": "dist/index.d.ts",