gbs-add-block 1.2.15 → 1.2.16

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 (129) hide show
  1. package/README.md +2 -2
  2. package/index.cjs +214 -21
  3. package/package.json +1 -1
  4. package/source/beta-components/breadcrumb/react/props.ts +2 -2
  5. package/source/beta-components/breadcrumb/styles.css +8 -8
  6. package/source/beta-components/button/react/props.ts +2 -2
  7. package/source/beta-components/button/styles.css +15 -15
  8. package/source/beta-components/checkbox/react/Checkbox.tsx +147 -146
  9. package/source/beta-components/checkbox/react/CheckboxGroup.tsx +8 -8
  10. package/source/beta-components/checkbox/react/props.ts +2 -2
  11. package/source/beta-components/checkbox/styles.css +11 -11
  12. package/source/beta-components/combobox/README.md +3 -3
  13. package/source/beta-components/combobox/react/MultiSelect.tsx +265 -263
  14. package/source/beta-components/combobox/react/Popover.tsx +38 -70
  15. package/source/beta-components/combobox/react/Select.tsx +200 -198
  16. package/source/beta-components/combobox/react/icons.tsx +6 -29
  17. package/source/beta-components/combobox/react/props.ts +4 -2
  18. package/source/beta-components/combobox/styles.css +18 -18
  19. package/source/beta-components/data-grid/react/Popover.tsx +35 -0
  20. package/source/beta-components/{datagrid → data-grid}/react/context.ts +2 -2
  21. package/source/beta-components/{datagrid → data-grid}/react/icons.tsx +8 -35
  22. package/source/beta-components/{datagrid → data-grid}/styles.css +24 -24
  23. package/source/beta-components/{datepicker → date-picker}/README.md +3 -3
  24. package/source/beta-components/{datepicker → date-picker}/react/DatePicker.tsx +249 -249
  25. package/source/beta-components/{datepicker → date-picker}/react/DateRangePicker.tsx +291 -291
  26. package/source/beta-components/date-picker/react/Popover.tsx +45 -0
  27. package/source/beta-components/date-picker/react/icons.tsx +15 -0
  28. package/source/beta-components/{datepicker → date-picker}/react/props.ts +2 -2
  29. package/source/beta-components/{datepicker → date-picker}/styles.css +18 -18
  30. package/source/beta-components/dialog/react/icons.tsx +16 -47
  31. package/source/beta-components/dialog/react/props.ts +2 -2
  32. package/source/beta-components/dialog/styles.css +21 -21
  33. package/source/beta-components/{fileuploader → file-uploader}/react/FileUploader.tsx +511 -515
  34. package/source/beta-components/{fileuploader → file-uploader}/react/icons.tsx +7 -27
  35. package/source/beta-components/{fileuploader → file-uploader}/react/props.ts +2 -2
  36. package/source/beta-components/{fileuploader → file-uploader}/styles.css +17 -17
  37. package/source/beta-components/input/core/count.ts +3 -12
  38. package/source/beta-components/input/react/Input.tsx +219 -219
  39. package/source/beta-components/input/react/OtpInput.tsx +256 -256
  40. package/source/beta-components/input/react/icons.tsx +3 -21
  41. package/source/beta-components/input/react/props.ts +2 -2
  42. package/source/beta-components/input/styles.css +15 -15
  43. package/source/beta-components/modal/react/Modal.tsx +242 -238
  44. package/source/beta-components/modal/react/icons.tsx +1 -19
  45. package/source/beta-components/modal/react/props.ts +2 -2
  46. package/source/beta-components/modal/styles.css +17 -13
  47. package/source/beta-components/shared/README.md +54 -0
  48. package/source/beta-components/shared/__tests__/boundaries.test.ts +95 -0
  49. package/source/beta-components/shared/__tests__/core.test.ts +55 -0
  50. package/source/beta-components/shared/core/cx.ts +9 -0
  51. package/source/beta-components/shared/core/field.ts +35 -0
  52. package/source/beta-components/shared/core/text.ts +14 -0
  53. package/source/beta-components/shared/index.ts +7 -0
  54. package/source/beta-components/shared/react/Popover.tsx +147 -0
  55. package/source/beta-components/shared/react/icons.tsx +74 -0
  56. package/source/beta-components/shared/react/useControllableState.ts +42 -0
  57. package/source/beta-components/shared/version.json +4 -0
  58. package/source/beta-components/shared/version.ts +6 -0
  59. package/source/beta-components/spinner/react/props.ts +2 -2
  60. package/source/beta-components/spinner/styles.css +5 -5
  61. package/source/beta-components/tabs/react/Tabs.tsx +258 -260
  62. package/source/beta-components/tabs/styles.css +15 -15
  63. package/source/beta-components/textarea/core/count.ts +3 -12
  64. package/source/beta-components/textarea/react/Textarea.tsx +208 -209
  65. package/source/beta-components/textarea/react/props.ts +2 -2
  66. package/source/beta-components/textarea/styles.css +12 -12
  67. package/source/beta-components/toaster/react/icons.tsx +19 -52
  68. package/source/beta-components/toaster/react/props.ts +2 -2
  69. package/source/beta-components/toaster/styles.css +18 -18
  70. package/source/beta-components/datagrid/react/Popover.tsx +0 -79
  71. package/source/beta-components/datepicker/react/Popover.tsx +0 -87
  72. package/source/beta-components/datepicker/react/icons.tsx +0 -32
  73. /package/source/beta-components/{datagrid → data-grid}/README.md +0 -0
  74. /package/source/beta-components/{datagrid → data-grid}/__tests__/core.test.ts +0 -0
  75. /package/source/beta-components/{datagrid → data-grid}/__tests__/export.test.ts +0 -0
  76. /package/source/beta-components/{datagrid → data-grid}/core/columnHelper.ts +0 -0
  77. /package/source/beta-components/{datagrid → data-grid}/core/columns.ts +0 -0
  78. /package/source/beta-components/{datagrid → data-grid}/core/filtering.ts +0 -0
  79. /package/source/beta-components/{datagrid → data-grid}/core/grid.ts +0 -0
  80. /package/source/beta-components/{datagrid → data-grid}/core/index.ts +0 -0
  81. /package/source/beta-components/{datagrid → data-grid}/core/rows.ts +0 -0
  82. /package/source/beta-components/{datagrid → data-grid}/core/sorting.ts +0 -0
  83. /package/source/beta-components/{datagrid → data-grid}/core/state.ts +0 -0
  84. /package/source/beta-components/{datagrid → data-grid}/core/store.ts +0 -0
  85. /package/source/beta-components/{datagrid → data-grid}/core/types.ts +0 -0
  86. /package/source/beta-components/{datagrid → data-grid}/core/values.ts +0 -0
  87. /package/source/beta-components/{datagrid → data-grid}/core/virtual.ts +0 -0
  88. /package/source/beta-components/{datagrid → data-grid}/export/csv.ts +0 -0
  89. /package/source/beta-components/{datagrid → data-grid}/export/download.ts +0 -0
  90. /package/source/beta-components/{datagrid → data-grid}/export/pdf.ts +0 -0
  91. /package/source/beta-components/{datagrid → data-grid}/export/table.ts +0 -0
  92. /package/source/beta-components/{datagrid → data-grid}/export/xlsx.ts +0 -0
  93. /package/source/beta-components/{datagrid → data-grid}/export/zip.ts +0 -0
  94. /package/source/beta-components/{datagrid → data-grid}/index.ts +0 -0
  95. /package/source/beta-components/{datagrid → data-grid}/react/Cell.tsx +0 -0
  96. /package/source/beta-components/{datagrid → data-grid}/react/ColumnMenu.tsx +0 -0
  97. /package/source/beta-components/{datagrid → data-grid}/react/DataGrid.tsx +0 -0
  98. /package/source/beta-components/{datagrid → data-grid}/react/FilterForm.tsx +0 -0
  99. /package/source/beta-components/{datagrid → data-grid}/react/HeaderRow.tsx +0 -0
  100. /package/source/beta-components/{datagrid → data-grid}/react/Pagination.tsx +0 -0
  101. /package/source/beta-components/{datagrid → data-grid}/react/Row.tsx +0 -0
  102. /package/source/beta-components/{datagrid → data-grid}/react/Toolbar.tsx +0 -0
  103. /package/source/beta-components/{datagrid → data-grid}/react/Viewport.tsx +0 -0
  104. /package/source/beta-components/{datagrid → data-grid}/react/hooks.ts +0 -0
  105. /package/source/beta-components/{datagrid → data-grid}/react/keyboard.ts +0 -0
  106. /package/source/beta-components/{datagrid → data-grid}/react/locale.ts +0 -0
  107. /package/source/beta-components/{datepicker → date-picker}/__tests__/core.test.ts +0 -0
  108. /package/source/beta-components/{datepicker → date-picker}/core/calendar.ts +0 -0
  109. /package/source/beta-components/{datepicker → date-picker}/core/format.ts +0 -0
  110. /package/source/beta-components/{datepicker → date-picker}/core/index.ts +0 -0
  111. /package/source/beta-components/{datepicker → date-picker}/core/types.ts +0 -0
  112. /package/source/beta-components/{datepicker → date-picker}/index.ts +0 -0
  113. /package/source/beta-components/{datepicker → date-picker}/react/Calendar.tsx +0 -0
  114. /package/source/beta-components/{datepicker → date-picker}/react/CalendarPanel.tsx +0 -0
  115. /package/source/beta-components/{datepicker → date-picker}/react/MonthYearPanels.tsx +0 -0
  116. /package/source/beta-components/{datepicker → date-picker}/react/locale.ts +0 -0
  117. /package/source/beta-components/{datepicker → date-picker}/react/useDatePicker.ts +0 -0
  118. /package/source/beta-components/{fileuploader → file-uploader}/README.md +0 -0
  119. /package/source/beta-components/{fileuploader → file-uploader}/__tests__/core.test.ts +0 -0
  120. /package/source/beta-components/{fileuploader → file-uploader}/core/format.ts +0 -0
  121. /package/source/beta-components/{fileuploader → file-uploader}/core/index.ts +0 -0
  122. /package/source/beta-components/{fileuploader → file-uploader}/core/store.ts +0 -0
  123. /package/source/beta-components/{fileuploader → file-uploader}/core/transport.ts +0 -0
  124. /package/source/beta-components/{fileuploader → file-uploader}/core/types.ts +0 -0
  125. /package/source/beta-components/{fileuploader → file-uploader}/core/validate.ts +0 -0
  126. /package/source/beta-components/{fileuploader → file-uploader}/index.ts +0 -0
  127. /package/source/beta-components/{fileuploader → file-uploader}/react/FileRow.tsx +0 -0
  128. /package/source/beta-components/{fileuploader → file-uploader}/react/locale.ts +0 -0
  129. /package/source/beta-components/{fileuploader → file-uploader}/react/useFileUploader.ts +0 -0
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # GBS Building Blocks 2.0 (v1.2.15)
1
+ # GBS Building Blocks 2.0 (v1.2.16)
2
2
 
3
3
  Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
4
4
 
@@ -10,7 +10,7 @@ For detailed documentation on usage and props, Please visit: [Building Block Doc
10
10
 
11
11
  New Beta Components are avilable for testing and feedback, Please visit: [Building Block Documentation v2.0.0 beta](https://gramprokit.vercel.app/2.0.0-beta)
12
12
 
13
- ## What's New 🎉 (Ver 1.2.15)
13
+ ## What's New 🎉 (Ver 1.2.16)
14
14
 
15
15
  - Update Candidate for next major change 2.0.0
16
16
 
package/index.cjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require("fs-extra");
4
4
  const path = require("path");
5
+ const crypto = require("crypto");
5
6
  const yargs = require("yargs/yargs");
6
7
  const { hideBin } = require("yargs/helpers");
7
8
  const readline = require("readline");
@@ -51,6 +52,12 @@ const CONFIG = {
51
52
  "Tabs",
52
53
  "Spinner",
53
54
  ],
55
+ // Beta folder names that are not simply the lowercased component name.
56
+ betaFolders: {
57
+ DataGrid: "data-grid",
58
+ DatePicker: "date-picker",
59
+ FileUploader: "file-uploader",
60
+ },
54
61
  // Define component dependencies
55
62
  dependencies: {
56
63
  FormRenderer: ["Select", "MultiSelect", "Input", "DatePicker"],
@@ -62,6 +69,24 @@ const SOURCE_PATH = path.join(__dirname, "source", "components");
62
69
  const BETA_SOURCE_PATH = path.join(__dirname, "source", "beta-components");
63
70
  const DEFAULT_DEST_PATH = path.join(process.cwd(), "component-lib");
64
71
 
72
+ /**
73
+ * Every beta component imports its shared helpers from `../../shared`, so this
74
+ * folder is installed alongside whatever the user picked. It is not a component
75
+ * and never appears in the component list.
76
+ */
77
+ const SHARED_DIR = "shared";
78
+ const MANIFEST_FILE = ".install-manifest.json";
79
+
80
+ /**
81
+ * Tests belong to this repo, not to the projects we install into: they import
82
+ * vitest, which the project has no reason to have, and the shared folder's
83
+ * boundary tests would run against whatever else is in the user's
84
+ * component-lib.
85
+ */
86
+ const TESTS_DIR = "__tests__";
87
+ const isTestPath = (filePath) =>
88
+ filePath.split(/[\\/]/).includes(TESTS_DIR);
89
+
65
90
  const normalizeComponent = (component, availableComponents) =>
66
91
  availableComponents.find(
67
92
  (available) => available.toLowerCase() === component.toLowerCase(),
@@ -72,6 +97,10 @@ const getAvailableComponents = (beta = false) =>
72
97
 
73
98
  const getSourcePath = (beta = false) => (beta ? BETA_SOURCE_PATH : SOURCE_PATH);
74
99
 
100
+ /** The folder a component lives in, which is not always its lowercased name. */
101
+ const folderFor = (component, beta = false) =>
102
+ (beta && CONFIG.betaFolders[component]) || component.toLowerCase();
103
+
75
104
  const copyCommonFiles = async (destPath) => {
76
105
  const commonFiles = [
77
106
  { src: ["..", "utils.ts"], dest: "utils.ts" },
@@ -88,18 +117,171 @@ const copyCommonFiles = async (destPath) => {
88
117
  }
89
118
  };
90
119
 
91
- const checkComponentExists = (component, destPath) => {
92
- const componentPath = path.join(destPath, component.toLowerCase());
120
+ /* ------------------------------------------------------------ shared folder */
121
+
122
+ const sha256 = (filePath) =>
123
+ crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
124
+
125
+ /** Every file under a directory, relative to it, with "/" separators. */
126
+ const listFiles = (dir, prefix = "") =>
127
+ fs
128
+ .readdirSync(path.join(dir, prefix), { withFileTypes: true })
129
+ .flatMap((entry) => {
130
+ const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
131
+ if (entry.name === MANIFEST_FILE || entry.name === TESTS_DIR) return [];
132
+ return entry.isDirectory() ? listFiles(dir, relative) : [relative];
133
+ });
134
+
135
+ /** -1, 0 or 1, comparing dotted numeric versions such as "1.2.0". */
136
+ const compareVersions = (a, b) => {
137
+ const left = String(a).split(".").map(Number);
138
+ const right = String(b).split(".").map(Number);
139
+ for (let i = 0; i < Math.max(left.length, right.length); i += 1) {
140
+ const diff = (left[i] || 0) - (right[i] || 0);
141
+ if (diff !== 0) return diff > 0 ? 1 : -1;
142
+ }
143
+ return 0;
144
+ };
145
+
146
+ const readJson = (filePath, fallback = null) => {
147
+ try {
148
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
149
+ } catch {
150
+ return fallback;
151
+ }
152
+ };
153
+
154
+ /** Files the manifest says we wrote, whose contents have since changed. */
155
+ const locallyEdited = (dest, manifest) =>
156
+ !manifest
157
+ ? []
158
+ : Object.keys(manifest.files).filter((file) => {
159
+ const target = path.join(dest, file);
160
+ return fs.existsSync(target) && manifest.files[file] !== sha256(target);
161
+ });
162
+
163
+ /**
164
+ * Installs or updates `shared/`.
165
+ *
166
+ * Because components are copied into a project one at a time, a project can end
167
+ * up with components built against different versions of this folder. The rules
168
+ * are that `shared/` only ever moves forward, and that a file the user has
169
+ * edited since we wrote it is never replaced without `--force`.
170
+ */
171
+ const installShared = async (destPath, { force = false } = {}) => {
172
+ const src = path.join(BETA_SOURCE_PATH, SHARED_DIR);
173
+ const dest = path.join(destPath, SHARED_DIR);
174
+
175
+ if (!fs.existsSync(src)) {
176
+ throw new Error(
177
+ `The shared folder is missing from ${BETA_SOURCE_PATH}. Beta components cannot be installed without it.`,
178
+ );
179
+ }
180
+
181
+ const srcVersion =
182
+ (readJson(path.join(src, "version.json"), {}) || {}).version || "0.0.0";
183
+ const manifest = readJson(path.join(dest, MANIFEST_FILE));
184
+ const installedVersion = manifest ? manifest.version : null;
185
+ const edited = locallyEdited(dest, manifest);
186
+
187
+ if (installedVersion && !force) {
188
+ const order = compareVersions(installedVersion, srcVersion);
189
+
190
+ if (order > 0) {
191
+ console.error(
192
+ `\n✗ This project has shared v${installedVersion}, newer than the v${srcVersion} in this installer.`,
193
+ );
194
+ console.error(
195
+ " Installing it would downgrade the folder and break the components already here.",
196
+ );
197
+ console.error(" Update the CLI, or re-run with --force to overwrite it anyway.");
198
+ process.exit(1);
199
+ }
200
+
201
+ if (order === 0) {
202
+ console.log(
203
+ edited.length > 0
204
+ ? `✓ shared v${installedVersion} is already installed (keeping your ${edited.length} edited file(s))`
205
+ : `✓ shared v${installedVersion} is already installed`,
206
+ );
207
+ return;
208
+ }
209
+ }
210
+
211
+ if (edited.length > 0 && !force) {
212
+ console.error(
213
+ `\n✗ These files in component-lib/${SHARED_DIR} have local changes:`,
214
+ );
215
+ edited.forEach((file) => console.error(` - ${file}`));
216
+ console.error(
217
+ "\n Updating shared/ would replace them. Re-run with --force to do that, or move",
218
+ );
219
+ console.error(
220
+ " your changes into your own module first: components are yours to edit,",
221
+ );
222
+ console.error(" shared/ is replaced on every update.");
223
+ process.exit(1);
224
+ }
225
+
226
+ const files = listFiles(src);
227
+ for (const file of files) {
228
+ await fs.copy(path.join(src, file), path.join(dest, file), { overwrite: true });
229
+ }
230
+
231
+ // Remove what an older version left behind, but only files we installed and
232
+ // the user has not since changed.
233
+ if (manifest) {
234
+ const removed = Object.keys(manifest.files).filter((file) => !files.includes(file));
235
+ for (const file of removed) {
236
+ const target = path.join(dest, file);
237
+ if (fs.existsSync(target) && (force || manifest.files[file] === sha256(target))) {
238
+ await fs.remove(target);
239
+ }
240
+ }
241
+ }
242
+
243
+ fs.writeJsonSync(
244
+ path.join(dest, MANIFEST_FILE),
245
+ {
246
+ version: srcVersion,
247
+ installedAt: new Date().toISOString(),
248
+ files: Object.fromEntries(
249
+ files.map((file) => [file, sha256(path.join(src, file))]),
250
+ ),
251
+ },
252
+ { spaces: 2 },
253
+ );
254
+
255
+ console.log(
256
+ installedVersion
257
+ ? `✓ shared updated ${installedVersion} → ${srcVersion}`
258
+ : `✓ shared v${srcVersion} installed`,
259
+ );
260
+ };
261
+
262
+ /** The files a component needs beside it, which differ between the two sets. */
263
+ const copySupportFiles = async (destPath, beta, options) => {
264
+ if (beta) {
265
+ await installShared(destPath, options);
266
+ return;
267
+ }
268
+ // The legacy components' common files. Beta components use none of them.
269
+ if (!fs.existsSync(path.join(destPath, "utils.ts"))) {
270
+ await copyCommonFiles(destPath);
271
+ }
272
+ };
273
+
274
+ /* -------------------------------------------------------------- components */
275
+
276
+ const checkComponentExists = (component, destPath, beta = false) => {
277
+ const componentPath = path.join(destPath, folderFor(component, beta));
93
278
  return fs.existsSync(componentPath);
94
279
  };
95
280
 
96
281
  const copyComponent = async (component, destPath, beta = false) => {
97
282
  try {
98
- const componentSrc = path.join(
99
- getSourcePath(beta),
100
- component.toLowerCase(),
101
- );
102
- const componentDest = path.join(destPath, component.toLowerCase());
283
+ const componentSrc = path.join(getSourcePath(beta), folderFor(component, beta));
284
+ const componentDest = path.join(destPath, folderFor(component, beta));
103
285
 
104
286
  if (!fs.existsSync(componentSrc)) {
105
287
  throw new Error(
@@ -107,7 +289,10 @@ const copyComponent = async (component, destPath, beta = false) => {
107
289
  );
108
290
  }
109
291
 
110
- await fs.copy(componentSrc, componentDest, { overwrite: true });
292
+ await fs.copy(componentSrc, componentDest, {
293
+ overwrite: true,
294
+ filter: (source) => !isTestPath(path.relative(componentSrc, source)),
295
+ });
111
296
  console.log(
112
297
  `✓ Component ${component} installed successfully ${
113
298
  component === "Grid"
@@ -134,7 +319,7 @@ const installComponentWithDependencies = async (
134
319
  const pendingInstalls = beta
135
320
  ? Array.from(componentsToInstall)
136
321
  : Array.from(componentsToInstall).filter(
137
- (comp) => !checkComponentExists(comp, destPath),
322
+ (comp) => !checkComponentExists(comp, destPath, beta),
138
323
  );
139
324
 
140
325
  if (pendingInstalls.length === 0) {
@@ -177,7 +362,7 @@ const installMultipleComponents = async (
177
362
  const pendingInstalls = beta
178
363
  ? Array.from(allComponentsToInstall)
179
364
  : Array.from(allComponentsToInstall).filter(
180
- (comp) => !checkComponentExists(comp, destPath),
365
+ (comp) => !checkComponentExists(comp, destPath, beta),
181
366
  );
182
367
 
183
368
  if (pendingInstalls.length === 0) {
@@ -254,11 +439,11 @@ const interactiveComponentSelector = async (beta = false) => {
254
439
 
255
440
  const handleKeyPress = (key) => {
256
441
  switch (key) {
257
- case "\u001b[A": // Up arrow
442
+ case "": // Up arrow
258
443
  currentIndex = Math.max(0, currentIndex - 1);
259
444
  renderMenu();
260
445
  break;
261
- case "\u001b[B": // Down arrow
446
+ case "": // Down arrow
262
447
  currentIndex = Math.min(
263
448
  getAvailableComponents(beta).length - 1,
264
449
  currentIndex + 1,
@@ -315,6 +500,11 @@ const validateComponents = (components, beta = false) => {
315
500
  (comp) => !availableComponents.includes(comp),
316
501
  );
317
502
  if (invalidComponents.length > 0) {
503
+ if (invalidComponents.some((comp) => comp.toLowerCase() === SHARED_DIR)) {
504
+ console.error(
505
+ "`shared` is not a component: it is installed automatically with any beta component.",
506
+ );
507
+ }
318
508
  console.error(`Invalid components: ${invalidComponents.join(", ")}`);
319
509
  console.log(`\nAvailable ${beta ? "beta " : ""}components:`);
320
510
  availableComponents.forEach((comp) => console.log(`- ${comp}`));
@@ -353,6 +543,11 @@ const main = async () => {
353
543
  type: "boolean",
354
544
  default: false,
355
545
  })
546
+ .option("force", {
547
+ describe: "Replace files in shared/ that you have edited locally",
548
+ type: "boolean",
549
+ default: false,
550
+ })
356
551
  .example("$0 -a Button", "Install a single component")
357
552
  .example("$0 -a Button,Card,Modal", "Install multiple components")
358
553
  .example("$0 -a DataGrid -beta", "Install the redesigned beta DataGrid")
@@ -370,7 +565,11 @@ const main = async () => {
370
565
  : "";
371
566
  console.log(`- ${comp}${deps}`);
372
567
  });
373
- if (!argv.beta) {
568
+ if (argv.beta) {
569
+ console.log(
570
+ `\nEvery beta component also installs component-lib/${SHARED_DIR}, which they all import.`,
571
+ );
572
+ } else {
374
573
  console.log("\nRedesigned beta components (install with -beta):");
375
574
  CONFIG.betaComponents.forEach((comp) => console.log(`- ${comp}`));
376
575
  }
@@ -391,10 +590,7 @@ const main = async () => {
391
590
  const destPath = DEFAULT_DEST_PATH;
392
591
  await fs.ensureDir(destPath);
393
592
 
394
- // Copy common files if they don't exist
395
- if (!fs.existsSync(path.join(destPath, "utils.ts"))) {
396
- await copyCommonFiles(destPath);
397
- }
593
+ await copySupportFiles(destPath, argv.beta, { force: argv.force });
398
594
 
399
595
  // Install selected components
400
596
  await installMultipleComponents(selectedComponents, destPath, argv.beta);
@@ -425,10 +621,7 @@ const main = async () => {
425
621
  const destPath = DEFAULT_DEST_PATH;
426
622
  await fs.ensureDir(destPath);
427
623
 
428
- // Copy common files if they don't exist
429
- if (!fs.existsSync(path.join(destPath, "utils.ts"))) {
430
- await copyCommonFiles(destPath);
431
- }
624
+ await copySupportFiles(destPath, argv.beta, { force: argv.force });
432
625
 
433
626
  // Install components
434
627
  if (components.length === 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gbs-add-block",
3
- "version": "1.2.15",
3
+ "version": "1.2.16",
4
4
  "description": "React Component Library",
5
5
  "type": "module",
6
6
  "files": [
@@ -10,5 +10,5 @@ export interface BreadcrumbLinkProps {
10
10
  onClick?: MouseEventHandler<HTMLAnchorElement>;
11
11
  }
12
12
 
13
- export const cx = (...names: (string | false | null | undefined)[]) =>
14
- names.filter(Boolean).join(" ");
13
+ // Shared with every other component, so class handling cannot drift.
14
+ export { cx } from "../../shared/core/cx";
@@ -1,20 +1,20 @@
1
1
  /*
2
2
  * Breadcrumb styles.
3
3
  *
4
- * Tokens read the DataGrid's --dg-* variables when they are set on an ancestor
5
- * (set them on :root to share one theme) and fall back to the same palette
6
- * otherwise. Rules live in the `components` layer, so utility classes passed
4
+ * Tokens read the shared --gbs-* variables when they are set on an ancestor
5
+ * (set them on :root to theme every component at once) and fall back to the
6
+ * same default palette otherwise. Rules live in the `components` layer, so utility classes passed
7
7
  * through `className` / `classNames` override them.
8
8
  */
9
9
  @layer theme, base, components, utilities;
10
10
 
11
11
  @layer components {
12
12
  .bc-root {
13
- --bc-fg: var(--dg-fg, light-dark(#18181b, #f4f4f5));
14
- --bc-muted: var(--dg-muted, light-dark(#71717a, #a1a1aa));
15
- --bc-hover: var(--dg-hover, light-dark(#f4f4f5, #1f1f23));
16
- --bc-focus: var(--dg-focus, light-dark(#2563eb, #60a5fa));
17
- --bc-font-size: var(--dg-font-size, 13px);
13
+ --bc-fg: var(--gbs-fg, var(--dg-fg, light-dark(#18181b, #f4f4f5)));
14
+ --bc-muted: var(--gbs-muted, var(--dg-muted, light-dark(#71717a, #a1a1aa)));
15
+ --bc-hover: var(--gbs-hover, var(--dg-hover, light-dark(#f4f4f5, #1f1f23)));
16
+ --bc-focus: var(--gbs-focus, var(--dg-focus, light-dark(#2563eb, #60a5fa)));
17
+ --bc-font-size: var(--gbs-font-size, var(--dg-font-size, 13px));
18
18
  /* Long labels are cut with an ellipsis; the full text is in the tooltip. */
19
19
  --bc-max-label: 24ch;
20
20
 
@@ -19,5 +19,5 @@ export interface ButtonRenderProps {
19
19
  [attribute: string]: unknown;
20
20
  }
21
21
 
22
- export const cx = (...names: (string | false | null | undefined)[]) =>
23
- names.filter(Boolean).join(" ");
22
+ // Shared with every other component, so class handling cannot drift.
23
+ export { cx } from "../../shared/core/cx";
@@ -1,27 +1,27 @@
1
1
  /*
2
2
  * Button styles.
3
3
  *
4
- * Tokens read the DataGrid's --dg-* variables when they are set on an ancestor
5
- * (set them on :root to share one theme) and fall back to the same palette
6
- * otherwise. Rules live in the `components` layer, so utility classes passed
4
+ * Tokens read the shared --gbs-* variables when they are set on an ancestor
5
+ * (set them on :root to theme every component at once) and fall back to the
6
+ * same default palette otherwise. Rules live in the `components` layer, so utility classes passed
7
7
  * through `className` / `classNames` override them.
8
8
  */
9
9
  @layer theme, base, components, utilities;
10
10
 
11
11
  @layer components {
12
12
  .bt-root {
13
- --bt-bg: var(--dg-bg, light-dark(#ffffff, #0b0b0e));
14
- --bt-fg: var(--dg-fg, light-dark(#18181b, #f4f4f5));
15
- --bt-border: var(--dg-border, light-dark(#e4e4e7, #27272a));
16
- --bt-hover: var(--dg-hover, light-dark(#f4f4f5, #1f1f23));
17
- --bt-subtle: light-dark(#f4f4f5, #1c1c20);
18
- --bt-accent: var(--dg-accent, light-dark(#2563eb, #60a5fa));
19
- --bt-accent-fg: var(--dg-accent-fg, light-dark(#ffffff, #0b1220));
20
- --bt-danger: var(--dg-danger, light-dark(#dc2626, #f87171));
21
- --bt-danger-fg: light-dark(#ffffff, #1c0606);
22
- --bt-focus: var(--dg-focus, light-dark(#2563eb, #60a5fa));
23
- --bt-radius: var(--dg-radius, 8px);
24
- --bt-font-size: var(--dg-font-size, 13px);
13
+ --bt-bg: var(--gbs-bg, var(--dg-bg, light-dark(#ffffff, #0b0b0e)));
14
+ --bt-fg: var(--gbs-fg, var(--dg-fg, light-dark(#18181b, #f4f4f5)));
15
+ --bt-border: var(--gbs-border, var(--dg-border, light-dark(#e4e4e7, #27272a)));
16
+ --bt-hover: var(--gbs-hover, var(--dg-hover, light-dark(#f4f4f5, #1f1f23)));
17
+ --bt-subtle: var(--gbs-subtle, light-dark(#f4f4f5, #1c1c20));
18
+ --bt-accent: var(--gbs-accent, var(--dg-accent, light-dark(#2563eb, #60a5fa)));
19
+ --bt-accent-fg: var(--gbs-accent-fg, var(--dg-accent-fg, light-dark(#ffffff, #0b1220)));
20
+ --bt-danger: var(--gbs-danger, var(--dg-danger, light-dark(#dc2626, #f87171)));
21
+ --bt-danger-fg: var(--gbs-danger-fg, light-dark(#ffffff, #1c0606));
22
+ --bt-focus: var(--gbs-focus, var(--dg-focus, light-dark(#2563eb, #60a5fa)));
23
+ --bt-radius: var(--gbs-radius, var(--dg-radius, 8px));
24
+ --bt-font-size: var(--gbs-font-size, var(--dg-font-size, 13px));
25
25
  --bt-height: 36px;
26
26
  --bt-px: 14px;
27
27
  --bt-gap: 8px;