@resolve-components/theme 1.0.0 → 1.2.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.
Files changed (49) hide show
  1. package/accordion/rc-accordion.scss +141 -0
  2. package/alert/rc-alert.scss +158 -0
  3. package/autocomplete/rc-autocomplete.scss +64 -0
  4. package/badge/rc-badge.scss +57 -0
  5. package/button/rc-button.scss +198 -0
  6. package/card/rc-card.scss +31 -0
  7. package/checkbox/rc-checkbox.scss +163 -0
  8. package/chip/rc-chip.scss +172 -0
  9. package/datepicker/rc-datepicker.scss +322 -0
  10. package/dialog/rc-dialog.scss +114 -0
  11. package/fesm2022/resolve-components-theme.mjs +44 -30
  12. package/fesm2022/resolve-components-theme.mjs.map +1 -1
  13. package/file-upload/rc-file-upload.scss +143 -0
  14. package/icon/rc-icon.scss +47 -0
  15. package/infinite-scroll/rc-infinite-scroll.scss +54 -0
  16. package/input/rc-input.scss +156 -0
  17. package/menu/rc-menu.scss +84 -0
  18. package/navbar/rc-navbar.scss +112 -0
  19. package/package.json +16 -9
  20. package/paginator/rc-paginator.scss +86 -0
  21. package/progress-bar/rc-progress-bar.scss +88 -0
  22. package/radio/rc-radio.scss +124 -0
  23. package/schematics/ng-add/index.js +149 -69
  24. package/schematics/ng-add/schema.json +15 -1
  25. package/select/rc-select.scss +197 -0
  26. package/sidenav/rc-sidenav.scss +154 -0
  27. package/slider/rc-slider.scss +311 -0
  28. package/spinner/rc-spinner.scss +106 -0
  29. package/{src/lib/styles → styles}/theming/_mapping.scss +2 -1
  30. package/table/rc-table.scss +147 -0
  31. package/tabs/rc-tabs.scss +155 -0
  32. package/toast/rc-toast.scss +228 -0
  33. package/toggle/rc-toggle.scss +138 -0
  34. package/tooltip/rc-tooltip.scss +34 -0
  35. package/tree/rc-tree.scss +114 -0
  36. package/types/resolve-components-theme.d.ts +32 -31
  37. package/virtual-scroll/rc-virtual-scroll.scss +38 -0
  38. /package/{src/lib/styles → styles}/_all.scss +0 -0
  39. /package/{src/lib/styles → styles}/_globals.scss +0 -0
  40. /package/{src/lib/styles → styles}/_themes.scss +0 -0
  41. /package/{src/lib/styles → styles}/_theming.scss +0 -0
  42. /package/{src/lib/styles → styles}/themes/_dark.scss +0 -0
  43. /package/{src/lib/styles → styles}/themes/_default.scss +0 -0
  44. /package/{src/lib/styles → styles}/theming/_animation.scss +0 -0
  45. /package/{src/lib/styles → styles}/theming/_functions.scss +0 -0
  46. /package/{src/lib/styles → styles}/theming/_get-value.scss +0 -0
  47. /package/{src/lib/styles → styles}/theming/_install.scss +0 -0
  48. /package/{src/lib/styles → styles}/theming/_register.scss +0 -0
  49. /package/{src/lib/styles → styles}/theming/_theming-variables.scss +0 -0
@@ -0,0 +1,86 @@
1
+ @use '../styles/theming' as *;
2
+
3
+ @include rc-install-component() {
4
+ .rc-paginator {
5
+ display: flex;
6
+ align-items: center;
7
+ flex-wrap: wrap;
8
+ width: 100%;
9
+ gap: rc-theme('paginator-gap');
10
+ padding: rc-theme('paginator-padding');
11
+ font-family: rc-theme('paginator-font-family');
12
+ font-size: rc-theme('paginator-font-size');
13
+ background: rc-theme('paginator-background');
14
+ border-top: 1px solid rc-theme('paginator-border-color');
15
+ }
16
+
17
+ .rc-paginator-size {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: 0.5rem;
21
+ margin-right: auto;
22
+ }
23
+
24
+ .rc-paginator-size-label {
25
+ color: rc-theme('paginator-size-label-color');
26
+ white-space: nowrap;
27
+ }
28
+
29
+ .rc-paginator-range {
30
+ color: rc-theme('paginator-range-color');
31
+ white-space: nowrap;
32
+ }
33
+
34
+ .rc-paginator-nav {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 0.125rem;
38
+ margin-left: auto;
39
+ }
40
+
41
+ .rc-paginator-ellipsis {
42
+ display: inline-flex;
43
+ align-items: center;
44
+ justify-content: center;
45
+ width: 2rem;
46
+ height: 2rem;
47
+ color: rc-theme('paginator-ellipsis-color');
48
+ pointer-events: none;
49
+ user-select: none;
50
+ }
51
+
52
+ // ── Mobile ────────────────────────────────────────────────────────────────
53
+ @media (max-width: 600px) {
54
+ .rc-paginator {
55
+ justify-content: center;
56
+ row-gap: 0.5rem;
57
+ }
58
+
59
+ // Size selector: own row, centered, no auto margin
60
+ .rc-paginator-size {
61
+ flex-basis: 100%;
62
+ justify-content: center;
63
+ margin-right: 0;
64
+ }
65
+
66
+ // Hide verbose "Rows per page:" label — just show the select
67
+ .rc-paginator-size-label {
68
+ display: none;
69
+ }
70
+
71
+ // Range: own centered row
72
+ .rc-paginator-range {
73
+ flex-basis: 100%;
74
+ text-align: center;
75
+ }
76
+
77
+ // Nav: centered, scrollable if too many page buttons
78
+ .rc-paginator-nav {
79
+ margin-left: 0;
80
+ overflow-x: auto;
81
+ max-width: 100%;
82
+ // thin scrollbar so it doesn't look terrible if scrolling is needed
83
+ scrollbar-width: thin;
84
+ }
85
+ }
86
+ }
@@ -0,0 +1,88 @@
1
+ @use '../styles/theming' as *;
2
+
3
+ @include rc-install-component() {
4
+ // ── Track ─────────────────────────────────────────────────────────────────
5
+ .rc-progress-bar {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 0.375rem;
9
+ width: 100%;
10
+ }
11
+
12
+ .rc-progress-bar-label {
13
+ display: flex;
14
+ justify-content: space-between;
15
+ font-family: rc-theme('progress-bar-label-font-family');
16
+ font-size: rc-theme('progress-bar-label-font-size');
17
+ color: rc-theme('progress-bar-label-color');
18
+ line-height: 1;
19
+ }
20
+
21
+ .rc-progress-bar-track {
22
+ position: relative;
23
+ width: 100%;
24
+ height: rc-theme('progress-bar-height');
25
+ background: rc-theme('progress-bar-background');
26
+ border-radius: rc-theme('progress-bar-border-radius');
27
+ overflow: hidden;
28
+ }
29
+
30
+ // ── Fill ──────────────────────────────────────────────────────────────────
31
+ .rc-progress-bar-fill {
32
+ height: 100%;
33
+ border-radius: inherit;
34
+ background: currentColor;
35
+ @include rc-component-animation(
36
+ width,
37
+ $duration: rc-theme('progress-bar-transition-duration')
38
+ );
39
+ }
40
+
41
+ // ── Status colors ────────────────────────────────────────────────────────
42
+ .rc-progress-bar-primary {
43
+ color: rc-theme('progress-bar-primary-color');
44
+ }
45
+ .rc-progress-bar-info {
46
+ color: rc-theme('progress-bar-info-color');
47
+ }
48
+ .rc-progress-bar-success {
49
+ color: rc-theme('progress-bar-success-color');
50
+ }
51
+ .rc-progress-bar-warning {
52
+ color: rc-theme('progress-bar-warning-color');
53
+ }
54
+ .rc-progress-bar-danger {
55
+ color: rc-theme('progress-bar-danger-color');
56
+ }
57
+
58
+ // ── Striped ───────────────────────────────────────────────────────────────
59
+ .rc-progress-bar-striped .rc-progress-bar-fill {
60
+ background-image: linear-gradient(
61
+ -45deg,
62
+ rgba(255, 255, 255, 0.18) 25%,
63
+ transparent 25%,
64
+ transparent 50%,
65
+ rgba(255, 255, 255, 0.18) 50%,
66
+ rgba(255, 255, 255, 0.18) 75%,
67
+ transparent 75%,
68
+ transparent
69
+ );
70
+ background-size: 1.5rem 1.5rem;
71
+ background-color: currentColor;
72
+ }
73
+
74
+ // ── Indeterminate ─────────────────────────────────────────────────────────
75
+ .rc-progress-bar-indeterminate .rc-progress-bar-fill {
76
+ width: 40% !important;
77
+ animation: rc-progress-indeterminate 1.4s ease-in-out infinite;
78
+ }
79
+
80
+ @keyframes rc-progress-indeterminate {
81
+ 0% {
82
+ transform: translateX(-100%);
83
+ }
84
+ 100% {
85
+ transform: translateX(350%);
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,124 @@
1
+ // =============================================================================
2
+ // rc-radio Resolve Components Radio Button (Themed)
3
+ // =============================================================================
4
+
5
+ @use '../styles/theming/get-value' as *;
6
+ @use '../styles/theming/install' as *;
7
+ @use '../styles/theming/animation' as *;
8
+
9
+ @include rc-install-component() {
10
+ .rc-radio-group {
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: rc-theme('radio-group-gap');
14
+
15
+ &-disabled {
16
+ opacity: rc-theme('radio-disabled-opacity');
17
+ pointer-events: none;
18
+ }
19
+ }
20
+
21
+ .rc-radio-button {
22
+ display: inline-flex;
23
+ align-items: center;
24
+ gap: rc-theme('radio-gap');
25
+ cursor: pointer;
26
+ user-select: none;
27
+ font-family: rc-theme('radio-font-family');
28
+ color: rc-theme('radio-text-color');
29
+
30
+ // ── Sizes ──────────────────────────────────────────────────────────────
31
+
32
+ &-sm {
33
+ font-size: rc-theme('radio-sm-font-size');
34
+
35
+ .rc-radio-button-control {
36
+ width: rc-theme('radio-sm-size');
37
+ height: rc-theme('radio-sm-size');
38
+ }
39
+
40
+ .rc-radio-button-dot {
41
+ width: rc-theme('radio-sm-dot-size');
42
+ height: rc-theme('radio-sm-dot-size');
43
+ }
44
+ }
45
+
46
+ &-md {
47
+ font-size: rc-theme('radio-md-font-size');
48
+
49
+ .rc-radio-button-control {
50
+ width: rc-theme('radio-md-size');
51
+ height: rc-theme('radio-md-size');
52
+ }
53
+
54
+ .rc-radio-button-dot {
55
+ width: rc-theme('radio-md-dot-size');
56
+ height: rc-theme('radio-md-dot-size');
57
+ }
58
+ }
59
+
60
+ // ── Disabled ─────────────────────────────────────────────────────────
61
+
62
+ &-disabled {
63
+ opacity: rc-theme('radio-disabled-opacity');
64
+ cursor: not-allowed;
65
+ }
66
+
67
+ // ── Checked ──────────────────────────────────────────────────────────
68
+
69
+ &-checked .rc-radio-button-control {
70
+ border-color: rc-theme('radio-checked-border-color');
71
+ background: rc-theme('radio-checked-background');
72
+ }
73
+
74
+ &-checked .rc-radio-button-dot {
75
+ background: rc-theme('radio-dot-color');
76
+ transform: scale(1);
77
+ opacity: 1;
78
+ }
79
+
80
+ // ── Focus ring ────────────────────────────────────────────────────────
81
+
82
+ &:focus-visible .rc-radio-button-control {
83
+ outline: 2px solid rc-theme('radio-focus-outline-color');
84
+ outline-offset: 2px;
85
+ }
86
+
87
+ // ── Hover (not disabled, not checked) ─────────────────────────────────
88
+
89
+ &:not(.rc-radio-button-disabled):not(.rc-radio-button-checked):hover {
90
+ .rc-radio-button-control {
91
+ border-color: rc-theme('radio-hover-border-color');
92
+ background: rc-theme('radio-hover-background');
93
+ }
94
+ }
95
+
96
+ // ── Parts ─────────────────────────────────────────────────────────────
97
+
98
+ &-control {
99
+ flex-shrink: 0;
100
+ display: flex;
101
+ align-items: center;
102
+ justify-content: center;
103
+ border-radius: 50%;
104
+ border: 2px solid rc-theme('radio-border-color');
105
+ background: rc-theme('radio-background');
106
+ @include rc-component-animation(
107
+ border-color background box-shadow,
108
+ $speed: 'medium'
109
+ );
110
+ }
111
+
112
+ &-dot {
113
+ border-radius: 50%;
114
+ background: rc-theme('radio-dot-color');
115
+ transform: scale(0);
116
+ opacity: 0;
117
+ @include rc-component-animation(transform opacity, $speed: 'medium');
118
+ }
119
+
120
+ &-label {
121
+ line-height: 1.5;
122
+ }
123
+ }
124
+ }
@@ -3,27 +3,101 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ngAdd = ngAdd;
4
4
  const schematics_1 = require("@angular-devkit/schematics");
5
5
  const tasks_1 = require("@angular-devkit/schematics/tasks");
6
- function getWorkspace(tree) {
7
- const file = tree.exists('angular.json')
6
+ // ---------------------------------------------------------------------------
7
+ // Helpers
8
+ // ---------------------------------------------------------------------------
9
+ const isNxWorkspace = (tree) => tree.exists('nx.json');
10
+ /**
11
+ * Try to resolve project config from a root angular.json / workspace.json.
12
+ * Works for standard Angular workspaces AND Nx workspaces that still maintain
13
+ * a root angular.json shim.
14
+ */
15
+ function getAngularWorkspaceProject(tree, projectName) {
16
+ const wsFile = tree.exists('angular.json')
8
17
  ? 'angular.json'
9
18
  : tree.exists('workspace.json')
10
19
  ? 'workspace.json'
11
20
  : null;
12
- if (!file)
21
+ if (!wsFile)
13
22
  return null;
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ let ws;
14
25
  try {
15
- const content = JSON.parse(tree.read(file).toString('utf-8'));
16
- return { file, content };
26
+ ws = JSON.parse(tree.read(wsFile).toString('utf-8'));
17
27
  }
18
28
  catch {
19
29
  return null;
20
30
  }
31
+ const resolved = projectName ??
32
+ ws['defaultProject'] ??
33
+ Object.keys(ws['projects'] ?? {})[0] ??
34
+ null;
35
+ if (!resolved)
36
+ return null;
37
+ const project = ws['projects']?.[resolved];
38
+ if (!project)
39
+ return null;
40
+ const sourceRoot = project['sourceRoot'] ?? 'src';
41
+ return {
42
+ file: wsFile,
43
+ projectName: resolved,
44
+ content: ws,
45
+ sourceRoot,
46
+ isNxProjectJson: false,
47
+ };
21
48
  }
22
- function resolveProjectName(ws, options) {
23
- if (options.project)
24
- return options.project;
25
- const c = ws.content;
26
- return c['defaultProject'] ?? Object.keys(c['projects'] ?? {})[0] ?? null;
49
+ /**
50
+ * In Nx v16+ workspaces there is no writable root angular.json.
51
+ * Discover project.json files under apps/ or projects/.
52
+ */
53
+ function getNxProjectJsonConfig(tree, projectName) {
54
+ const candidates = [];
55
+ if (projectName) {
56
+ candidates.push(`apps/${projectName}/project.json`, `libs/${projectName}/project.json`, `${projectName}/project.json`);
57
+ }
58
+ // Auto-discover under apps/ and projects/
59
+ for (const root of ['apps', 'projects']) {
60
+ const dir = tree.getDir(root);
61
+ for (const sub of dir.subdirs) {
62
+ const p = `${root}/${sub}/project.json`;
63
+ if (!candidates.includes(p))
64
+ candidates.push(p);
65
+ }
66
+ }
67
+ for (const path of candidates) {
68
+ if (!tree.exists(path))
69
+ continue;
70
+ try {
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ const content = JSON.parse(tree.read(path).toString('utf-8'));
73
+ // Skip non-application projects (libraries, e2e, etc.)
74
+ if (content['projectType'] && content['projectType'] !== 'application')
75
+ continue;
76
+ const projName = content['name'] ?? path.split('/')[1];
77
+ const defaultSourceRoot = path.split('/').slice(0, -1).join('/') + '/src';
78
+ const sourceRoot = content['sourceRoot'] ?? defaultSourceRoot;
79
+ return {
80
+ file: path,
81
+ projectName: projName,
82
+ content,
83
+ sourceRoot,
84
+ isNxProjectJson: true,
85
+ };
86
+ }
87
+ catch {
88
+ continue;
89
+ }
90
+ }
91
+ return null;
92
+ }
93
+ function resolveProjectConfig(tree, options) {
94
+ const nx = isNxWorkspace(tree);
95
+ // Prefer reading from project.json in Nx workspaces (it's always writable)
96
+ if (nx) {
97
+ return (getNxProjectJsonConfig(tree, options.project ?? null) ??
98
+ getAngularWorkspaceProject(tree, options.project ?? null));
99
+ }
100
+ return getAngularWorkspaceProject(tree, options.project ?? null);
27
101
  }
28
102
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
103
  function getBuildOptions(project) {
@@ -32,100 +106,103 @@ function getBuildOptions(project) {
32
106
  null);
33
107
  }
34
108
  // ---------------------------------------------------------------------------
35
- // Rule: patch angular.json
109
+ // Rule: patch build config (angular.json or Nx project.json)
36
110
  // ---------------------------------------------------------------------------
37
- function addAngularJsonConfig(options) {
38
- return (tree) => {
39
- const ws = getWorkspace(tree);
40
- if (!ws)
41
- return tree;
42
- const projectName = resolveProjectName(ws, options);
43
- if (!projectName)
111
+ function addBuildConfig(options) {
112
+ return (tree, ctx) => {
113
+ const cfg = resolveProjectConfig(tree, options);
114
+ if (!cfg) {
115
+ ctx.logger.warn('⚠ Could not locate a build config (angular.json / project.json).\n' +
116
+ ' Add the following manually to your project build options:\n' +
117
+ ' • styles: ["node_modules/@angular/cdk/overlay-prebuilt.css"]\n' +
118
+ ' • stylePreprocessorOptions.includePaths: ["node_modules/@resolve-components/theme/styles"]');
44
119
  return tree;
45
- const project = ws.content['projects']?.[projectName];
46
- if (!project)
47
- return tree;
48
- const buildOptions = getBuildOptions(project);
49
- if (!buildOptions)
120
+ }
121
+ ctx.logger.info(` Configuring project: ${cfg.projectName} (${cfg.file})`);
122
+ // In angular.json the project lives under projects[name]; in project.json it IS the root
123
+ const buildTarget = cfg.isNxProjectJson
124
+ ? cfg.content
125
+ : cfg.content['projects']?.[cfg.projectName];
126
+ const buildOptions = getBuildOptions(buildTarget);
127
+ if (!buildOptions) {
128
+ ctx.logger.warn('⚠ Could not find build target options — add them manually.');
50
129
  return tree;
51
- // ── styles: prepend CDK overlay CSS ──
130
+ }
131
+ // ── styles: add CDK overlay CSS ──
52
132
  const cdkStyle = 'node_modules/@angular/cdk/overlay-prebuilt.css';
53
- if (!Array.isArray(buildOptions['styles'])) {
133
+ if (!Array.isArray(buildOptions['styles']))
54
134
  buildOptions['styles'] = [];
55
- }
56
135
  if (!buildOptions['styles'].includes(cdkStyle)) {
57
136
  buildOptions['styles'].unshift(cdkStyle);
58
137
  }
59
138
  // ── stylePreprocessorOptions: add includePath ──
60
139
  const includePath = 'node_modules/@resolve-components/theme/styles';
61
140
  buildOptions['stylePreprocessorOptions'] ??= {};
62
- const paths = (buildOptions['stylePreprocessorOptions']['includePaths'] ??= []);
63
- if (!paths.includes(includePath)) {
141
+ const paths = buildOptions['stylePreprocessorOptions']['includePaths'] ?? [];
142
+ buildOptions['stylePreprocessorOptions']['includePaths'] = paths;
143
+ if (!paths.includes(includePath))
64
144
  paths.unshift(includePath);
65
- }
66
- tree.overwrite(ws.file, JSON.stringify(ws.content, null, 2));
145
+ tree.overwrite(cfg.file, JSON.stringify(cfg.content, null, 2));
67
146
  return tree;
68
147
  };
69
148
  }
70
149
  // ---------------------------------------------------------------------------
71
150
  // Rule: add provideRcTheme() to app.config.ts
72
151
  // ---------------------------------------------------------------------------
73
- function addProviderToConfig() {
74
- return (tree) => {
75
- const configPath = 'src/app/app.config.ts';
76
- if (!tree.exists(configPath))
152
+ function addProviderToConfig(options) {
153
+ return (tree, ctx) => {
154
+ const cfg = resolveProjectConfig(tree, options);
155
+ const sourceRoot = cfg?.sourceRoot ?? 'src';
156
+ const configPath = `${sourceRoot}/app/app.config.ts`;
157
+ if (!tree.exists(configPath)) {
158
+ ctx.logger.warn(`⚠ ${configPath} not found — add provideRcTheme() manually.`);
77
159
  return tree;
160
+ }
78
161
  let content = tree.read(configPath).toString('utf-8');
79
162
  if (content.includes('provideRcTheme'))
80
163
  return tree;
81
- // Insert import after the last existing @angular import
164
+ const themeName = options.theme ?? 'default';
165
+ // Append import after the last existing import line
82
166
  const importLine = `import { provideRcTheme } from '@resolve-components/theme';\n`;
83
- const lastAngularImportMatch = [...content.matchAll(/^import .*;\n/gm)].pop();
84
- if (lastAngularImportMatch) {
85
- const insertAt = lastAngularImportMatch.index + lastAngularImportMatch[0].length;
86
- content = content.slice(0, insertAt) + importLine + content.slice(insertAt);
167
+ const lastImportMatch = [...content.matchAll(/^import .*;\n/gm)].pop();
168
+ if (lastImportMatch) {
169
+ const insertAt = lastImportMatch.index + lastImportMatch[0].length;
170
+ content =
171
+ content.slice(0, insertAt) + importLine + content.slice(insertAt);
87
172
  }
88
173
  else {
89
174
  content = importLine + content;
90
175
  }
91
- // Insert provider at start of providers array
92
- content = content.replace(/(providers:\s*\[)/, `$1\n provideRcTheme({ name: 'default' }),`);
176
+ // Prepend provider inside the providers array
177
+ content = content.replace(/(providers:\s*\[)/, `$1\n provideRcTheme({ name: '${themeName}' }),`);
93
178
  tree.overwrite(configPath, content);
179
+ ctx.logger.info(` Added provideRcTheme({ name: '${themeName}' }) → ${configPath}`);
94
180
  return tree;
95
181
  };
96
182
  }
97
183
  // ---------------------------------------------------------------------------
98
184
  // Rule: prepend @use / @include to styles.scss
99
185
  // ---------------------------------------------------------------------------
100
- function addGlobalStyles() {
101
- return (tree) => {
102
- const stylesPath = 'src/styles.scss';
103
- if (!tree.exists(stylesPath))
186
+ function addGlobalStyles(options) {
187
+ return (tree, ctx) => {
188
+ const cfg = resolveProjectConfig(tree, options);
189
+ const sourceRoot = cfg?.sourceRoot ?? 'src';
190
+ const stylesPath = `${sourceRoot}/styles.scss`;
191
+ if (!tree.exists(stylesPath)) {
192
+ ctx.logger.warn(`⚠ ${stylesPath} not found.\n` +
193
+ ` Add the following to your global stylesheet:\n` +
194
+ ` @use 'all' as *;\n @include rc-install();`);
104
195
  return tree;
196
+ }
105
197
  let content = tree.read(stylesPath).toString('utf-8');
106
- if (content.includes('@resolve-components/theme') || content.includes(`@use 'all'`)) {
198
+ if (content.includes('@resolve-components/theme') ||
199
+ content.includes(`@use 'all'`)) {
107
200
  return tree;
108
201
  }
109
- const addition = [
110
- `@use 'all';`,
111
- `@use 'theming/install' as *;`,
112
- ``,
113
- `@include rc-install() {`,
114
- ` *,`,
115
- ` *::before,`,
116
- ` *::after { box-sizing: border-box; }`,
117
- ``,
118
- ` body {`,
119
- ` margin: 0;`,
120
- ` font-family: rc-theme('font-family-primary');`,
121
- ` font-size: rc-theme('text-body-font-size');`,
122
- ` color: rc-theme('text-basic-color');`,
123
- ` background-color: rc-theme('background-basic-color-1');`,
124
- ` }`,
125
- `}`,
126
- ``,
127
- ].join('\n');
202
+ // Minimal two-line setup — rc-install() emits all global resets and CSS vars
203
+ const addition = `@use 'all' as *;\n\n// Emit CSS custom property blocks\n@include rc-install();\n\n`;
128
204
  tree.overwrite(stylesPath, addition + content);
205
+ ctx.logger.info(` Updated ${stylesPath} with @use 'all' as * and @include rc-install()`);
129
206
  return tree;
130
207
  };
131
208
  }
@@ -134,13 +211,16 @@ function addGlobalStyles() {
134
211
  // ---------------------------------------------------------------------------
135
212
  function ngAdd(options) {
136
213
  return (tree, context) => {
137
- context.logger.info('Installing @resolve-components/theme…');
214
+ const nx = isNxWorkspace(tree);
215
+ context.logger.info(`\n🚀 Setting up @resolve-components/theme${nx ? ' (Nx monorepo detected)' : ''}…\n`);
138
216
  return (0, schematics_1.chain)([
139
- addAngularJsonConfig(options),
140
- addProviderToConfig(),
141
- addGlobalStyles(),
217
+ addBuildConfig(options),
218
+ addProviderToConfig(options),
219
+ addGlobalStyles(options),
142
220
  (_tree, ctx) => {
143
221
  ctx.addTask(new tasks_1.NodePackageInstallTask());
222
+ ctx.logger.info('\n✅ @resolve-components/theme setup complete!');
223
+ ctx.logger.info(' Restart your dev server to apply the new Sass includePaths.\n');
144
224
  },
145
225
  ])(tree, context);
146
226
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema",
3
- "id": "SchematicsResolveComponentsNgAdd",
3
+ "$id": "SchematicsResolveComponentsNgAdd",
4
4
  "title": "Add @resolve-components/theme to an Angular project",
5
5
  "type": "object",
6
6
  "properties": {
@@ -10,6 +10,20 @@
10
10
  "$default": {
11
11
  "$source": "projectName"
12
12
  }
13
+ },
14
+ "theme": {
15
+ "type": "string",
16
+ "description": "The default visual theme to install.",
17
+ "default": "default",
18
+ "enum": ["default", "dark"],
19
+ "x-prompt": {
20
+ "message": "Which default theme would you like to use?",
21
+ "type": "list",
22
+ "items": [
23
+ { "value": "default", "label": "\u2600\uFE0F Light (default)" },
24
+ { "value": "dark", "label": "\uD83C\uDF19 Dark" }
25
+ ]
26
+ }
13
27
  }
14
28
  }
15
29
  }