create-ec-app 1.5.0 → 1.7.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 (34) hide show
  1. package/README.md +86 -21
  2. package/dist/cssScope.d.ts +4 -0
  3. package/dist/cssScope.d.ts.map +1 -0
  4. package/dist/cssScope.js +124 -0
  5. package/dist/cssScope.js.map +1 -0
  6. package/dist/index.js +28 -94
  7. package/dist/index.js.map +1 -1
  8. package/dist/pcf.d.ts.map +1 -1
  9. package/dist/pcf.js +13 -84
  10. package/dist/pcf.js.map +1 -1
  11. package/dist/portalContainers.d.ts +7 -0
  12. package/dist/portalContainers.d.ts.map +1 -0
  13. package/dist/portalContainers.js +118 -0
  14. package/dist/portalContainers.js.map +1 -0
  15. package/package.json +6 -3
  16. package/scripts/check-generated-css-scope.mjs +98 -37
  17. package/templates/base/src/App.tsx +1 -1
  18. package/templates/base/src/index.css +1 -4
  19. package/templates/base/src/main.tsx +1 -4
  20. package/templates/pcf/base/README.md +28 -9
  21. package/templates/pcf/base/index.ts +30 -6
  22. package/templates/pcf/base/runtime/PcfAppShell.tsx +17 -0
  23. package/templates/pcf/base/runtime/emptyStyles.js +1 -0
  24. package/templates/pcf/base/webpack.config.js +13 -0
  25. package/templates/targets/code-apps/README.md +246 -0
  26. package/templates/targets/code-apps/package.patch.json +8 -0
  27. package/templates/targets/code-apps/power.config.example.json +14 -0
  28. package/templates/targets/code-apps/vite.config.patch.ts +15 -0
  29. package/templates/targets/power-pages/src/App.patch.tsx +1 -1
  30. package/templates/targets/webresource/README.md +21 -7
  31. package/templates/ui/kendo/src/main.patch.tsx +1 -4
  32. package/templates/ui/shadcn-ui/components.json +1 -1
  33. package/templates/ui/shadcn-ui/src/index.patch.css +9 -26
  34. package/templates/base/src/runtime/EcAppShell.tsx +0 -29
@@ -4,7 +4,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
4
 
5
5
  import App from "{{PROJECT_APP_IMPORT}}";
6
6
  import "{{PROJECT_CSS_IMPORT}}";
7
- import { EcAppShell } from "{{PROJECT_EC_APP_SHELL_IMPORT}}";
7
+ import { PcfAppShell } from "./runtime/PcfAppShell";
8
8
  import type { IInputs, IOutputs } from "./control/generated/ManifestTypes";
9
9
  import type {
10
10
  PcfRuntimeContext,
@@ -16,13 +16,37 @@ function sanitizeGuid(value: string | null | undefined): string | null {
16
16
  return value.replace(/[{}]/g, "");
17
17
  }
18
18
 
19
+ function getPageClientUrl(
20
+ pageContext:
21
+ | {
22
+ clientUrl?: unknown;
23
+ getClientUrl?: unknown;
24
+ }
25
+ | undefined,
26
+ ): string | null {
27
+ const getClientUrl = pageContext?.getClientUrl;
28
+ if (typeof getClientUrl === "function") {
29
+ try {
30
+ const clientUrl = getClientUrl.call(pageContext);
31
+ return typeof clientUrl === "string" ? clientUrl : null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+
37
+ return typeof pageContext?.clientUrl === "string"
38
+ ? pageContext.clientUrl
39
+ : null;
40
+ }
41
+
19
42
  function getContextInfo(context: ComponentFramework.Context<IInputs>) {
20
43
  const pageContext = (
21
44
  context as ComponentFramework.Context<IInputs> & {
22
45
  page?: {
46
+ clientUrl?: unknown;
23
47
  entityId?: string;
24
48
  entityTypeName?: string;
25
- getClientUrl?: () => string;
49
+ getClientUrl?: unknown;
26
50
  };
27
51
  }
28
52
  ).page;
@@ -39,7 +63,7 @@ function getContextInfo(context: ComponentFramework.Context<IInputs>) {
39
63
  ),
40
64
  entityName:
41
65
  modeContextInfo?.entityTypeName ?? pageContext?.entityTypeName ?? null,
42
- clientUrl: pageContext?.getClientUrl?.() ?? null,
66
+ clientUrl: getPageClientUrl(pageContext),
43
67
  userId: sanitizeGuid(context.userSettings.userId),
44
68
  };
45
69
  }
@@ -112,8 +136,8 @@ export class {{PCF_CONSTRUCTOR}}
112
136
  _state: ComponentFramework.Dictionary,
113
137
  container: HTMLDivElement,
114
138
  ): void {
115
- container.classList.add("ec-pcf-shell-control");
116
- container.dataset.ecPcfControl = "{{PCF_CONSTRUCTOR}}";
139
+ container.classList.add("pcf-shell-control");
140
+ container.dataset.pcfControl = "{{PCF_CONSTRUCTOR}}";
117
141
  this.runtime = createRuntime(context);
118
142
  this.root = createRoot(container);
119
143
  this.render();
@@ -144,7 +168,7 @@ export class {{PCF_CONSTRUCTOR}}
144
168
  StrictMode,
145
169
  null,
146
170
  React.createElement(
147
- EcAppShell,
171
+ PcfAppShell,
148
172
  null,
149
173
  React.createElement(
150
174
  QueryClientProvider,
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+
3
+ import { PortalContainerContext } from "{{PROJECT_PORTAL_CONTAINER_IMPORT}}";
4
+
5
+ export function PcfAppShell({ children }: { children: React.ReactNode }) {
6
+ const [portalContainer, setPortalContainer] =
7
+ React.useState<HTMLDivElement | null>(null);
8
+
9
+ return (
10
+ <div data-pcf-app-root="">
11
+ <PortalContainerContext.Provider value={portalContainer}>
12
+ {children}
13
+ <div data-pcf-portal-root="" ref={setPortalContainer} />
14
+ </PortalContainerContext.Provider>
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1 @@
1
+ module.exports = {};
@@ -1,4 +1,7 @@
1
1
  const path = require("path");
2
+ const webpack = require("webpack");
3
+
4
+ const projectSrcPath = path.resolve(__dirname, "{{PROJECT_SRC_ALIAS}}");
2
5
 
3
6
  module.exports = {
4
7
  resolve: {
@@ -8,4 +11,14 @@ module.exports = {
8
11
  "react-dom": path.resolve(__dirname, "{{PROJECT_REACT_DOM_ALIAS}}"),
9
12
  },
10
13
  },
14
+ plugins: [
15
+ new webpack.NormalModuleReplacementPlugin(
16
+ /\.(css|scss|sass)$/,
17
+ (resource) => {
18
+ if (path.resolve(resource.context).startsWith(projectSrcPath)) {
19
+ resource.request = path.resolve(__dirname, "runtime/emptyStyles.js");
20
+ }
21
+ },
22
+ ),
23
+ ],
11
24
  };
@@ -0,0 +1,246 @@
1
+ # EC Power Apps Code App
2
+
3
+ React + TypeScript template for Power Apps code apps. Generated by `create-ec-app`, it keeps the EC base app structure, Tailwind setup, TanStack Query provider, and selected UI layer, then adds Microsoft Power Apps code app support through `@microsoft/power-apps` and `@microsoft/power-apps-vite`.
4
+
5
+ ## Features
6
+
7
+ - React + TypeScript with Vite
8
+ - Tailwind CSS
9
+ - UI library choice: Kendo UI or shadcn/ui
10
+ - TanStack Query provider pre-wired in `src/main.tsx`
11
+ - Power Apps SDK dependency for code app APIs and generated connector services
12
+ - Power Apps Vite plugin for local play URLs, Power Apps CORS support, and `base: "./"` build output
13
+
14
+ ## Prerequisites
15
+
16
+ - Node.js LTS and npm
17
+ - Git
18
+ - A Power Platform environment with Power Apps code apps enabled
19
+ - A Power Apps Premium license for users who run the code app
20
+
21
+ Admins enable code apps in Power Platform admin center by opening the target environment, then Settings > Product > Features, and turning on **Power Apps code apps**.
22
+
23
+ ## Getting Started
24
+
25
+ Install dependencies if they were not installed during scaffolding:
26
+
27
+ ```bash
28
+ npm install
29
+ ```
30
+
31
+ Initialize the code app metadata and authenticate against your Power Platform environment:
32
+
33
+ ```bash
34
+ npx power-apps init --display-name "{{APP_NAME}}" --environment-id <environment-id> --app-url http://localhost:5173
35
+ ```
36
+
37
+ You can omit the options and run `npx power-apps init` to answer the interactive prompts instead. The command creates `power.config.json`, which the Power Apps SDK, Vite plugin, and deployment commands use.
38
+
39
+ This template includes `power.config.example.json` only as a reference. Do not rename it before running `npx power-apps init`; the Microsoft CLI refuses to initialize when a real `power.config.json` already exists. The generated `power.config.json` includes your environment ID, app metadata, build settings, and connection/data references. It does not contain authentication tokens, but it is environment-specific, so decide whether to commit it based on your ALM flow.
40
+
41
+ ## Local Development
42
+
43
+ Start the app locally:
44
+
45
+ ```bash
46
+ npm run dev
47
+ ```
48
+
49
+ The Power Apps Vite plugin prints a **Local Play** URL. Open that URL in the same browser profile you use for your Power Platform tenant so authentication and connector calls work as expected.
50
+
51
+ If browser local network access restrictions appear, allow the browser prompt for the local endpoint. For iframe embedding scenarios, Microsoft recommends adding `allow="local-network-access"` to the iframe.
52
+
53
+ ## Data Access
54
+
55
+ Code apps should not use the Dynamics webresource `AuthService`/`token.json` pattern. In a code app, the Power Apps host manages end-user authentication, and `@microsoft/power-apps` plus generated services perform data requests through Power Platform connectors and Dataverse references.
56
+
57
+ The normal flow is:
58
+
59
+ 1. Create or identify the connection in [Power Apps](https://make.powerapps.com).
60
+ 2. Add the data source to this project with the Power Apps CLI.
61
+ 3. Import the generated model and service files from `src/generated`.
62
+ 4. Build and push the app with `npx power-apps push`.
63
+
64
+ ### Connect to Dataverse
65
+
66
+ After `npx power-apps init`, add a Dataverse table by logical name:
67
+
68
+ ```bash
69
+ npx power-apps add-data-source --api-id dataverse --resource-name <table-logical-name>
70
+ ```
71
+
72
+ Example:
73
+
74
+ ```bash
75
+ npx power-apps add-data-source --api-id dataverse --resource-name account
76
+ ```
77
+
78
+ The CLI updates `power.config.json` and generates typed files under `src/generated/models` and `src/generated/services`. For example, after adding Accounts you can use the generated service:
79
+
80
+ ```ts
81
+ import { AccountsService } from "./generated/services/AccountsService";
82
+ import type { Accounts } from "./generated/models/AccountsModel";
83
+
84
+ export async function listAccounts() {
85
+ const result = await AccountsService.getAll({
86
+ select: ["name", "accountnumber"],
87
+ top: 50,
88
+ });
89
+
90
+ return result.data ?? [];
91
+ }
92
+
93
+ export async function createAccount(name: string) {
94
+ const account = { name } satisfies Partial<Accounts>;
95
+ const result = await AccountsService.create(
96
+ account as Omit<Accounts, "accountid">,
97
+ );
98
+
99
+ return result.data;
100
+ }
101
+ ```
102
+
103
+ For Dataverse CRUD, use the generated service methods such as `create`, `get`, `getAll`, `update`, and `delete`. Prefer `select` when reading data so the app retrieves only the columns it needs.
104
+
105
+ ### Connect to Other Power Platform Connectors
106
+
107
+ For non-Dataverse connectors, first create or locate the connection in Power Apps, then get the API name and connection ID. You can use the Power Apps maker portal or:
108
+
109
+ ```bash
110
+ pac connection list
111
+ ```
112
+
113
+ Add a non-tabular connector data source:
114
+
115
+ ```bash
116
+ npx power-apps add-data-source --api-id <api-name> --connection-id <connection-id>
117
+ ```
118
+
119
+ Add a tabular connector data source such as SQL or SharePoint:
120
+
121
+ ```bash
122
+ npx power-apps add-data-source \
123
+ --api-id <api-name> \
124
+ --connection-id <connection-id> \
125
+ --resource-name <table-or-list-name> \
126
+ --dataset <dataset-name>
127
+ ```
128
+
129
+ You can discover datasets and tables through the npm CLI:
130
+
131
+ ```bash
132
+ npx power-apps list-datasets --api-id <api-name> --connection-id <connection-id>
133
+ npx power-apps list-tables --api-id <api-name> --connection-id <connection-id> --dataset <dataset-name>
134
+ ```
135
+
136
+ For ALM-friendly apps, prefer connection references instead of binding directly to a maker's connection:
137
+
138
+ ```bash
139
+ npx power-apps list-connection-references --solution-id <solution-id>
140
+ npx power-apps add-data-source \
141
+ --api-id <api-name> \
142
+ --connection-ref <connection-reference-logical-name> \
143
+ --solution-id <solution-id>
144
+ ```
145
+
146
+ For tabular connectors, environment variable references can be used for dataset and table values:
147
+
148
+ ```bash
149
+ npx power-apps add-data-source \
150
+ --api-id shared_sharepointonline \
151
+ --connection-id <connection-id> \
152
+ --dataset "@envvar:<site-environment-variable-schema-name>" \
153
+ --resource-name "@envvar:<list-environment-variable-schema-name>"
154
+ ```
155
+
156
+ ### Dataverse Actions and Functions
157
+
158
+ Dataverse actions and functions use the newer npm-only commands:
159
+
160
+ ```bash
161
+ npx power-apps find-dataverse-api --search "WhoAmI"
162
+ npx power-apps add-dataverse-api --api-name WhoAmI
163
+ ```
164
+
165
+ The command updates `power.config.json`, writes schema files, and generates a service such as:
166
+
167
+ ```ts
168
+ import { WhoAmIService } from "./generated/services/WhoAmIService";
169
+
170
+ const result = await WhoAmIService.WhoAmI();
171
+ ```
172
+
173
+ ### Runtime Context
174
+
175
+ Use `getContext` from the Power Apps SDK when you need app, environment, user, query parameter, or session details:
176
+
177
+ ```ts
178
+ import { getContext } from "@microsoft/power-apps/app";
179
+
180
+ const context = await getContext();
181
+
182
+ console.log(context.app.environmentId);
183
+ console.log(context.user.userPrincipalName);
184
+ console.log(context.host.sessionId);
185
+ ```
186
+
187
+ This replaces most webresource-style assumptions about `window.Xrm`, parent frame context, or manually loaded local tokens.
188
+
189
+ ## Code Apps vs Webresources
190
+
191
+ This target is intentionally different from the `webresource` target:
192
+
193
+ - Webresources run inside Dynamics 365/model-driven app pages and can use `window.Xrm`; Code Apps run in the Power Apps host.
194
+ - Webresources in this repo use `src/services/AuthService.ts` and `token.json` for local Dataverse Web API calls; Code Apps should use `@microsoft/power-apps`, `power.config.json`, and generated services.
195
+ - The Code Apps scaffold removes webresource/Power Pages auth artifacts if they are present during generation.
196
+ - Webresource builds are tuned for web resource upload with deterministic `main.css`/JS files; Code Apps builds are published with `npx power-apps push`.
197
+ - Code Apps can use Power Platform connectors, connection references, environment variables, generated Dataverse CRUD services, and generated Dataverse action/function services as part of the platform hosting model.
198
+
199
+ ## Build and Deploy
200
+
201
+ Build the production assets:
202
+
203
+ ```bash
204
+ npm run build
205
+ ```
206
+
207
+ Publish a new version to the environment configured in `power.config.json`:
208
+
209
+ ```bash
210
+ npx power-apps push
211
+ ```
212
+
213
+ When the push succeeds, the command returns a Power Apps URL where you can run the app. You can also open [Power Apps](https://make.powerapps.com) to play, share, or review the app details.
214
+
215
+ ## Solution and ALM Notes
216
+
217
+ For healthy ALM, use a non-default solution. If your environment has a preferred solution, new code apps are saved there by default when deployed. To target a specific solution with the PAC CLI path, use:
218
+
219
+ ```bash
220
+ pac code push --solutionName <solution-name>
221
+ ```
222
+
223
+ If you already deployed the app and need to add it to a solution manually, open Power Apps, go to Solutions, choose the solution, then select Add existing > App > Code app.
224
+
225
+ Microsoft's current npm CLI is the preferred path for new code app work. Older docs still show the PAC CLI flow:
226
+
227
+ ```bash
228
+ pac auth create
229
+ pac env select --environment <environment-id>
230
+ pac code init --displayname "{{APP_NAME}}"
231
+ npm run build | pac code push
232
+ ```
233
+
234
+ Use the npm CLI unless you specifically need a PAC CLI option that has not moved yet.
235
+
236
+ ## Related Microsoft Documentation
237
+
238
+ - [Power Apps code apps overview](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview)
239
+ - [Quickstart with npm CLI](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/npm-quickstart)
240
+ - [Code apps architecture](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/architecture)
241
+ - [Connect your code app to data](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/connect-to-data)
242
+ - [Connect your code app to Dataverse](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/connect-to-dataverse)
243
+ - [Add a Dataverse action or function](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/add-dataverse-action-function)
244
+ - [Get context data](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/retrieve-context)
245
+ - [Use environment variables in data sources](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/use-environment-variables)
246
+ - [Application lifecycle management for code apps](https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/alm)
@@ -0,0 +1,8 @@
1
+ {
2
+ "dependencies": {
3
+ "@microsoft/power-apps": "^1.1.9"
4
+ },
5
+ "devDependencies": {
6
+ "@microsoft/power-apps-vite": "^1.0.2"
7
+ }
8
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "version": "1.0",
3
+ "appId": null,
4
+ "appDisplayName": "{{APP_NAME}}",
5
+ "region": "prod",
6
+ "environmentId": "<environment-id>",
7
+ "description": " ",
8
+ "buildPath": "./dist",
9
+ "buildEntryPoint": "index.html",
10
+ "localAppUrl": "http://localhost:5173",
11
+ "logoPath": "Default",
12
+ "connectionReferences": {},
13
+ "databaseReferences": {}
14
+ }
@@ -0,0 +1,15 @@
1
+ import path from "node:path";
2
+ import tailwindcss from "@tailwindcss/vite";
3
+ import react from "@vitejs/plugin-react";
4
+ import { powerApps } from "@microsoft/power-apps-vite/plugin";
5
+ import { defineConfig } from "vite";
6
+
7
+ // https://vite.dev/config/
8
+ export default defineConfig({
9
+ plugins: [react(), tailwindcss(), powerApps()],
10
+ resolve: {
11
+ alias: {
12
+ "@": path.resolve(__dirname, "./src"),
13
+ },
14
+ },
15
+ });
@@ -4,7 +4,7 @@ function App() {
4
4
  const { isAuthenticated, user } = useAuth(); //INFO: User is where the token information is stored (user?.idToken)
5
5
 
6
6
  return (
7
- <div className="ec:flex ec:flex-col ec:items-center ec:justify-center ec:h-screen ec:gap-4">
7
+ <div className="flex h-screen flex-col items-center justify-center gap-4">
8
8
  {isAuthenticated ? (
9
9
  <div>You are logged in</div>
10
10
  ) : (
@@ -270,10 +270,15 @@ Basic flow:
270
270
  npm run build
271
271
  ```
272
272
 
273
- 2. Run the generator and point `--pcf-dir` at the generated PCF project directory:
273
+ 2. Run the generator from the webresource root. Point `--pcf-dir` at the webresource root and `--output` at the PCF project folder you want to generate:
274
274
 
275
275
  ```bash
276
- npx create-ec-app@latest --pcf-dir ./pcf/{{ControlName}} namespace {{EC}} --constructor {{ControlName}} --display-name "Control Name"
276
+ npx create-ec-app@latest \
277
+ --pcf-dir . \
278
+ --output ./pcf/{{ControlName}} \
279
+ --namespace EC \
280
+ --constructor {{ControlName}} \
281
+ --display-name "Control Name"
277
282
  ```
278
283
 
279
284
  3. Install dependencies inside that generated PCF directory:
@@ -281,32 +286,41 @@ npx create-ec-app@latest --pcf-dir ./pcf/{{ControlName}} namespace {{EC}} --cons
281
286
  ```bash
282
287
  cd ./pcf/{{ControlName}}
283
288
  npm install
289
+ npm run build
284
290
  ```
285
291
 
286
292
  This writes a standalone PCF project to the `--pcf-dir` folder. The generated control:
287
293
 
288
294
  - imports `src/App.tsx` directly instead of wrapping built HTML in an iframe
289
- - reuses the built stylesheet from `dist/main.css`
295
+ - creates and imports `pcf-scoped.css` from the built `dist/main.css`
296
+ - scopes every non-keyframe CSS selector under the generated PCF host selector
290
297
  - creates `src/runtime/types.ts` only if that file does not already exist
291
298
  - provides a runtime object with record context and `context.webAPI` access inside the generated PCF shell, following the `PcfBase` pattern
292
299
  - mounts your React app directly into the PCF container
293
300
 
294
- Typical conversion flow from inside a generated webresource project:
301
+ Regenerate after app code or CSS changes by running the same sequence again from the webresource root:
295
302
 
296
303
  ```bash
297
- npm install
298
304
  npm run build
299
- npx create-ec-app@latest --pcf-dir ./pcf/FusionNotebookHost namespace EC --constructor FusionNotebookHost --display-name "Fusion Notebook Host"
305
+ npx create-ec-app@latest \
306
+ --pcf-dir . \
307
+ --output ./pcf/FusionNotebookHost \
308
+ --namespace EC \
309
+ --constructor FusionNotebookHost \
310
+ --display-name "Fusion Notebook Host"
300
311
  cd pcf/FusionNotebookHost
301
312
  npm install
302
313
  npm run build
303
314
  ```
304
315
 
316
+ Regeneration removes and recreates the PCF output folder, so keep durable app code in `src` and use generator templates or layers for repeatable PCF-specific changes.
317
+
305
318
  What gets generated:
306
319
 
307
320
  - a minimal PCF wrapper project under `pcf/<ConstructorName>`
308
321
  - a checked-in PCF shell stamped out from `create-ec-app/templates/pcf/base`
309
- - direct imports back to your webresource source and built CSS
322
+ - direct imports back to your webresource source
323
+ - a generated `pcf-scoped.css` file with CSS selectors scoped to the PCF control
310
324
 
311
325
  ## Notes
312
326
 
@@ -4,7 +4,6 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
4
  import "@progress/kendo-theme-fluent/dist/all.css";
5
5
  import "./index.css";
6
6
  import App from "./App.tsx";
7
- import { EcAppShell } from "./runtime/EcAppShell.tsx";
8
7
 
9
8
  const queryClient = new QueryClient({
10
9
  defaultOptions: {
@@ -24,9 +23,7 @@ const root = createRoot(document.getElementById("root")!);
24
23
  root.render(
25
24
  <StrictMode>
26
25
  <QueryClientProvider client={queryClient}>
27
- <EcAppShell>
28
- <App />
29
- </EcAppShell>
26
+ <App />
30
27
  </QueryClientProvider>
31
28
  </StrictMode>
32
29
  );
@@ -8,7 +8,7 @@
8
8
  "css": "src/index.css",
9
9
  "baseColor": "neutral",
10
10
  "cssVariables": true,
11
- "prefix": "ec"
11
+ "prefix": ""
12
12
  },
13
13
  "iconLibrary": "lucide",
14
14
  "rtl": false,
@@ -1,12 +1,9 @@
1
- @layer theme, base, components, utilities;
2
-
3
- @import "tailwindcss/theme.css" layer(theme) prefix(ec) important;
4
- @import "tailwindcss/utilities.css" layer(utilities) prefix(ec) important;
5
- @import "tw-animate-css/prefix";
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
6
3
  @import "shadcn/tailwind.css";
7
4
 
8
5
  @custom-variant hover (&:hover);
9
- @custom-variant dark (&:is(.ec-app.dark *, .ec-app .dark *));
6
+ @custom-variant dark (&:is(.dark *));
10
7
 
11
8
  @theme inline {
12
9
  --radius-sm: calc(var(--radius) - 4px);
@@ -46,7 +43,7 @@
46
43
  --color-sidebar-ring: var(--sidebar-ring);
47
44
  }
48
45
 
49
- .ec-app[data-ec-app-id="{{APP_NAME}}"] {
46
+ :root {
50
47
  --radius: 0.625rem;
51
48
  --background: oklch(1 0 0);
52
49
  --foreground: oklch(0.145 0 0);
@@ -79,13 +76,9 @@
79
76
  --sidebar-accent-foreground: oklch(0.205 0 0);
80
77
  --sidebar-border: oklch(0.922 0 0);
81
78
  --sidebar-ring: oklch(0.708 0 0);
82
-
83
- background: var(--background);
84
- color: var(--foreground);
85
79
  }
86
80
 
87
- .ec-app[data-ec-app-id="{{APP_NAME}}"].dark,
88
- .ec-app[data-ec-app-id="{{APP_NAME}}"] .dark {
81
+ .dark {
89
82
  --background: oklch(0.145 0 0);
90
83
  --foreground: oklch(0.985 0 0);
91
84
  --card: oklch(0.205 0 0);
@@ -120,20 +113,10 @@
120
113
  }
121
114
 
122
115
  @layer base {
123
- :where(.ec-app, .ec-app *, .ec-app *::before, .ec-app *::after) {
124
- box-sizing: border-box;
125
- }
126
-
127
- :where(.ec-app *) {
128
- border-color: var(--border);
129
- outline-color: color-mix(in oklab, var(--ring) 50%, transparent);
116
+ * {
117
+ @apply border-border outline-ring/50;
130
118
  }
131
-
132
- :where(.ec-app button, .ec-app input, .ec-app select, .ec-app textarea) {
133
- font: inherit;
134
- }
135
-
136
- :where(.ec-app button:not(:disabled), .ec-app [role="button"]:not(:disabled)) {
137
- cursor: pointer;
119
+ body {
120
+ @apply bg-background text-foreground;
138
121
  }
139
122
  }
@@ -1,29 +0,0 @@
1
- import * as React from "react";
2
-
3
- export const EC_APP_SCOPE_CLASS = "ec-app";
4
- export const EC_APP_ID = "{{APP_NAME}}";
5
- export const EC_PCF_SCOPE_CLASS = "ec-pcf-shell-control";
6
-
7
- const EcPortalContainerContext = React.createContext<HTMLElement | null>(null);
8
-
9
- export function useEcPortalContainer() {
10
- return React.useContext(EcPortalContainerContext);
11
- }
12
-
13
- export function EcAppShell({ children }: { children: React.ReactNode }) {
14
- const [portalContainer, setPortalContainer] =
15
- React.useState<HTMLDivElement | null>(null);
16
-
17
- return (
18
- <div
19
- className={EC_APP_SCOPE_CLASS}
20
- data-ec-app-id={EC_APP_ID}
21
- data-ec-app-root=""
22
- >
23
- <EcPortalContainerContext.Provider value={portalContainer}>
24
- {children}
25
- <div data-ec-portal-root="" ref={setPortalContainer} />
26
- </EcPortalContainerContext.Provider>
27
- </div>
28
- );
29
- }