@g3nomaly/ui 0.3.3 → 0.3.5
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.
- package/README.md +49 -26
- package/dist/cli/adapter.d.ts +25 -8
- package/dist/cli/adapter.d.ts.map +1 -1
- package/dist/cli/adapter.js +34 -20
- package/dist/cli/adapter.js.map +1 -1
- package/dist/cli/afterInstall.d.ts +26 -0
- package/dist/cli/afterInstall.d.ts.map +1 -0
- package/dist/cli/afterInstall.js +54 -0
- package/dist/cli/afterInstall.js.map +1 -0
- package/dist/cli/commands/add.d.ts +8 -2
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/add.js +10 -5
- package/dist/cli/commands/add.js.map +1 -1
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +16 -5
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +59 -13
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/ls.d.ts +1 -1
- package/dist/cli/commands/ls.js +1 -1
- package/dist/cli/commands/ls.js.map +1 -1
- package/dist/cli/commands/manifest.js +1 -1
- package/dist/cli/commands/manifest.js.map +1 -1
- package/dist/cli/commands/source.d.ts +4 -1
- package/dist/cli/commands/source.d.ts.map +1 -1
- package/dist/cli/commands/source.js +29 -2
- package/dist/cli/commands/source.js.map +1 -1
- package/dist/cli/commands/sourceInit.d.ts +9 -0
- package/dist/cli/commands/sourceInit.d.ts.map +1 -0
- package/dist/cli/commands/sourceInit.js +78 -0
- package/dist/cli/commands/sourceInit.js.map +1 -0
- package/dist/cli/commands/update.d.ts +10 -3
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +9 -4
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +17 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/localSources.d.ts +12 -0
- package/dist/cli/localSources.d.ts.map +1 -0
- package/dist/cli/localSources.js +49 -0
- package/dist/cli/localSources.js.map +1 -0
- package/dist/cli/npmDependencies.d.ts +11 -0
- package/dist/cli/npmDependencies.d.ts.map +1 -0
- package/dist/cli/npmDependencies.js +73 -0
- package/dist/cli/npmDependencies.js.map +1 -0
- package/dist/cli/packageFiles.d.ts +15 -0
- package/dist/cli/packageFiles.d.ts.map +1 -0
- package/dist/cli/packageFiles.js +54 -0
- package/dist/cli/packageFiles.js.map +1 -0
- package/dist/cli/themeTokens.d.ts +12 -0
- package/dist/cli/themeTokens.d.ts.map +1 -0
- package/dist/cli/themeTokens.js +60 -0
- package/dist/cli/themeTokens.js.map +1 -0
- package/dist/packages/dependencies.d.ts +48 -0
- package/dist/packages/dependencies.d.ts.map +1 -0
- package/dist/packages/dependencies.js +66 -0
- package/dist/packages/dependencies.js.map +1 -0
- package/dist/packages/install.d.ts +30 -0
- package/dist/packages/install.d.ts.map +1 -0
- package/dist/packages/install.js +54 -0
- package/dist/packages/install.js.map +1 -0
- package/dist/packages/localPack.d.ts +48 -0
- package/dist/packages/localPack.d.ts.map +1 -0
- package/dist/packages/localPack.js +72 -0
- package/dist/packages/localPack.js.map +1 -0
- package/dist/registry/adapters/shadcn.adapter.d.ts +32 -7
- package/dist/registry/adapters/shadcn.adapter.d.ts.map +1 -1
- package/dist/registry/adapters/shadcn.adapter.js +75 -20
- package/dist/registry/adapters/shadcn.adapter.js.map +1 -1
- package/dist/registry/adapters/shadcnImports.d.ts +10 -0
- package/dist/registry/adapters/shadcnImports.d.ts.map +1 -0
- package/dist/registry/adapters/shadcnImports.js +18 -0
- package/dist/registry/adapters/shadcnImports.js.map +1 -0
- package/dist/registry/componentsJson.d.ts +6 -1
- package/dist/registry/componentsJson.d.ts.map +1 -1
- package/dist/registry/componentsJson.js +34 -1
- package/dist/registry/componentsJson.js.map +1 -1
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/manifest.d.ts +2 -13
- package/dist/registry/manifest.d.ts.map +1 -1
- package/dist/registry/manifest.js +4 -76
- package/dist/registry/manifest.js.map +1 -1
- package/dist/registry/packageExports.d.ts +9 -0
- package/dist/registry/packageExports.d.ts.map +1 -0
- package/dist/registry/packageExports.js +50 -0
- package/dist/registry/packageExports.js.map +1 -0
- package/dist/registry/packageImports.d.ts +23 -0
- package/dist/registry/packageImports.d.ts.map +1 -0
- package/dist/registry/packageImports.js +51 -0
- package/dist/registry/packageImports.js.map +1 -0
- package/dist/registry/readSource.d.ts +4 -2
- package/dist/registry/readSource.d.ts.map +1 -1
- package/dist/registry/readSource.js +27 -3
- package/dist/registry/readSource.js.map +1 -1
- package/dist/registry/types.d.ts +86 -3
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/types.js +46 -3
- package/dist/registry/types.js.map +1 -1
- package/dist/sources/builtins.d.ts +1 -5
- package/dist/sources/builtins.d.ts.map +1 -1
- package/dist/sources/builtins.js +2 -7
- package/dist/sources/builtins.js.map +1 -1
- package/dist/theme/cssVars.d.ts +43 -0
- package/dist/theme/cssVars.d.ts.map +1 -0
- package/dist/theme/cssVars.js +107 -0
- package/dist/theme/cssVars.js.map +1 -0
- package/dist/theme/detectCssFile.d.ts +9 -0
- package/dist/theme/detectCssFile.d.ts.map +1 -0
- package/dist/theme/detectCssFile.js +41 -0
- package/dist/theme/detectCssFile.js.map +1 -0
- package/package.json +8 -21
- package/template/build.ts +32 -0
- package/template/package.json +22 -0
- package/template/src/components/example/Example.css +20 -0
- package/template/src/components/example/Example.tsx +26 -0
- package/template/src/components/example/example.meta.ts +69 -0
- package/dist/components/basic/Card.css +0 -32
- package/dist/components/basic/Card.debug.ts +0 -5
- package/dist/components/basic/Card.tsx +0 -31
- package/dist/components/basic/CardFooter.css +0 -16
- package/dist/components/basic/CardFooter.debug.ts +0 -5
- package/dist/components/basic/CardFooter.tsx +0 -29
- package/dist/components/basic/CardHeader.css +0 -14
- package/dist/components/basic/CardHeader.debug.ts +0 -5
- package/dist/components/basic/CardHeader.tsx +0 -29
- package/dist/components/basic/card.meta.ts +0 -14
- package/dist/components/basic/cardfooter.meta.ts +0 -14
- package/dist/components/basic/cardheader.meta.ts +0 -14
- package/dist/components/input/Button.css +0 -34
- package/dist/components/input/Button.debug.ts +0 -5
- package/dist/components/input/Button.tsx +0 -28
- package/dist/components/input/button.meta.ts +0 -14
- package/dist/components.json +0 -138
package/dist/registry/types.js
CHANGED
|
@@ -10,9 +10,37 @@ export const ComponentFileTypeSchema = z.enum([
|
|
|
10
10
|
"type",
|
|
11
11
|
"meta",
|
|
12
12
|
]);
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* @brief How a file reaches the app: `copy` (the default) writes it into the app for the user to own;
|
|
15
|
+
* `package` keeps it in the source package, where the component imports it from by package path.
|
|
16
|
+
*/
|
|
17
|
+
export const FileInstallSchema = z.enum(["copy", "package"]);
|
|
18
|
+
/**
|
|
19
|
+
* @brief One file of a component; `path` is relative to the components directory, e.g. `basic/Card.tsx`.
|
|
20
|
+
*
|
|
21
|
+
* @property install - `package` for a file that stays in the source package, such as a store; absent to copy it.
|
|
22
|
+
*/
|
|
14
23
|
export const ComponentFileSchema = BaseFileEntrySchema.extend({
|
|
15
24
|
type: ComponentFileTypeSchema,
|
|
25
|
+
install: FileInstallSchema.optional(),
|
|
26
|
+
});
|
|
27
|
+
/**
|
|
28
|
+
* @brief npm packages a component's files import, each as `name` or `name@range`, e.g. `radix-ui` or
|
|
29
|
+
* `recharts@3.8.0`, the way shadcn lists them.
|
|
30
|
+
*/
|
|
31
|
+
export const NpmDependenciesSchema = z.array(z.string().min(1));
|
|
32
|
+
/**
|
|
33
|
+
* @brief Theme tokens a component needs in the app's global stylesheet, in shadcn's `cssVars` format:
|
|
34
|
+
* names without the leading `--`, e.g. `{ light: { sidebar: "oklch(0.98 0 0)" } }`.
|
|
35
|
+
*
|
|
36
|
+
* @property theme - Tokens for the `@theme inline` block.
|
|
37
|
+
* @property light - Tokens for the `:root` block.
|
|
38
|
+
* @property dark - Tokens for the `.dark` block.
|
|
39
|
+
*/
|
|
40
|
+
export const CssVarsSchema = z.object({
|
|
41
|
+
theme: z.record(z.string(), z.string()).optional(),
|
|
42
|
+
light: z.record(z.string(), z.string()).optional(),
|
|
43
|
+
dark: z.record(z.string(), z.string()).optional(),
|
|
16
44
|
});
|
|
17
45
|
/**
|
|
18
46
|
* @brief A component as it ships: what a `*.meta.ts` file declares and what
|
|
@@ -20,7 +48,11 @@ export const ComponentFileSchema = BaseFileEntrySchema.extend({
|
|
|
20
48
|
*
|
|
21
49
|
* @property version - Set at build time from the package version.
|
|
22
50
|
* @property registryDependencies - Keys of components this one needs installed beside it, e.g. `button`.
|
|
23
|
-
* @property
|
|
51
|
+
* @property dependencies - npm packages the app needs at runtime for this component, e.g. `radix-ui`.
|
|
52
|
+
* @property devDependencies - npm packages the app needs at build time only, e.g. `@types/d3`.
|
|
53
|
+
* @property cssVars - Theme tokens the component needs in the app's global stylesheet.
|
|
54
|
+
* @property files - Files of the component, each with its path and `ComponentFileType`; `install: "package"`
|
|
55
|
+
* marks one that stays in the package.
|
|
24
56
|
*/
|
|
25
57
|
export const PackagedComponentSchema = z.object({
|
|
26
58
|
name: z.string().min(1),
|
|
@@ -29,20 +61,31 @@ export const PackagedComponentSchema = z.object({
|
|
|
29
61
|
category: z.string().optional(),
|
|
30
62
|
author: z.string().optional(),
|
|
31
63
|
registryDependencies: z.array(z.string()).optional(),
|
|
64
|
+
dependencies: NpmDependenciesSchema.optional(),
|
|
65
|
+
devDependencies: NpmDependenciesSchema.optional(),
|
|
66
|
+
cssVars: CssVarsSchema.optional(),
|
|
32
67
|
files: z.array(ComponentFileSchema).min(1),
|
|
33
68
|
});
|
|
34
69
|
/**
|
|
35
70
|
* @brief One installable component, read from a source by `readComponentSource`
|
|
36
|
-
* or the shadcn adapter, and written per install into the
|
|
71
|
+
* or the shadcn adapter, and written per install into the ui manifest by
|
|
37
72
|
* the `add` and `update` commands.
|
|
38
73
|
*
|
|
39
74
|
* @property group - Display group: the category, or the first folder of the first file, e.g. `basic`.
|
|
75
|
+
* @property dependencies - npm packages the app needs at runtime for this component.
|
|
76
|
+
* @property devDependencies - npm packages the app needs at build time only.
|
|
77
|
+
* @property cssVars - Theme tokens the component needs in the app's global stylesheet.
|
|
40
78
|
* @property files - Files the install writes, each with its path and `ComponentFileType`.
|
|
79
|
+
* @property packageFiles - Files that stay in the source package, imported from it by package path; never written.
|
|
41
80
|
*/
|
|
42
81
|
export const ComponentMetaSchema = OriginEntrySchema.extend({
|
|
43
82
|
group: z.string().min(1),
|
|
44
83
|
category: z.string().optional(),
|
|
45
84
|
author: z.string().optional(),
|
|
85
|
+
dependencies: NpmDependenciesSchema.optional(),
|
|
86
|
+
devDependencies: NpmDependenciesSchema.optional(),
|
|
87
|
+
cssVars: CssVarsSchema.optional(),
|
|
46
88
|
files: z.array(ComponentFileSchema).min(1),
|
|
89
|
+
packageFiles: z.array(ComponentFileSchema).optional(),
|
|
47
90
|
});
|
|
48
91
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,WAAW;IACX,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;CACP,CAAC,CAAC;AAKH,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import type { SourceRecord } from "@g3nomaly/core/sources";
|
|
2
|
-
/**
|
|
3
|
-
* @brief Sources every project has without registering them; they cannot be
|
|
4
|
-
* removed. `g3nui` is this package's own folder, so the components always
|
|
5
|
-
* match the CLI that installs them.
|
|
6
|
-
*/
|
|
2
|
+
/** Sources every project has without registering them; they cannot be removed. */
|
|
7
3
|
export declare const BUILTIN_SOURCES: SourceRecord;
|
|
8
4
|
//# sourceMappingURL=builtins.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,kFAAkF;AAClF,eAAO,MAAM,eAAe,EAAE,YAE7B,CAAC"}
|
package/dist/sources/builtins.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* @brief Sources every project has without registering them; they cannot be
|
|
4
|
-
* removed. `g3nui` is this package's own folder, so the components always
|
|
5
|
-
* match the CLI that installs them.
|
|
6
|
-
*/
|
|
1
|
+
/** Sources every project has without registering them; they cannot be removed. */
|
|
7
2
|
export const BUILTIN_SOURCES = {
|
|
8
|
-
|
|
3
|
+
"g3n-ui": { kind: "npm", package: "@g3nomaly/g3n-ui" },
|
|
9
4
|
};
|
|
10
5
|
//# sourceMappingURL=builtins.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.js","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"builtins.js","sourceRoot":"","sources":["../../src/sources/builtins.ts"],"names":[],"mappings":"AAGA,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAiB;IAC3C,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE;CACvD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { CssVars } from "../registry/types";
|
|
2
|
+
/**
|
|
3
|
+
* @brief One token added to a stylesheet.
|
|
4
|
+
*
|
|
5
|
+
* @property block - Selector of the block it went into, e.g. `:root`.
|
|
6
|
+
* @property name - Its name with the leading `--`, e.g. `--sidebar`.
|
|
7
|
+
* @property value - Its value, e.g. `oklch(0.98 0 0)`.
|
|
8
|
+
*/
|
|
9
|
+
export interface AddedToken {
|
|
10
|
+
block: string;
|
|
11
|
+
name: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @brief The result of adding tokens to a stylesheet.
|
|
16
|
+
*
|
|
17
|
+
* @property css - The stylesheet with the missing tokens added.
|
|
18
|
+
* @property added - Each token added, in block order.
|
|
19
|
+
*/
|
|
20
|
+
export interface CssVarsMerge {
|
|
21
|
+
css: string;
|
|
22
|
+
added: AddedToken[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @brief Adds the theme tokens a stylesheet lacks: `light` to `:root`, `dark` to `.dark`, `theme` to
|
|
26
|
+
* `@theme inline`. When the stylesheet has a `@theme` block (Tailwind v4), each token whose value is a
|
|
27
|
+
* colour also gets its `--color-<name>: var(--<name>)` mapping there, the way shadcn adds them, so
|
|
28
|
+
* Tailwind classes such as `bg-sidebar` work. Tokens the stylesheet defines, in any block of the same
|
|
29
|
+
* kind, keep their value: the app's theme wins.
|
|
30
|
+
*
|
|
31
|
+
* @param css - The stylesheet, e.g. the contents of `src/index.css`.
|
|
32
|
+
* @param vars - Tokens to add.
|
|
33
|
+
* @returns The stylesheet with the missing tokens added, and which were added.
|
|
34
|
+
*/
|
|
35
|
+
export declare function addCssVars(css: string, vars: CssVars): CssVarsMerge;
|
|
36
|
+
/**
|
|
37
|
+
* @brief Merges the theme tokens of several components; the first component naming a token wins.
|
|
38
|
+
*
|
|
39
|
+
* @param all - Tokens per component, in install order.
|
|
40
|
+
* @returns One set of tokens.
|
|
41
|
+
*/
|
|
42
|
+
export declare function mergeCssVars(all: readonly CssVars[]): CssVars;
|
|
43
|
+
//# sourceMappingURL=cssVars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssVars.d.ts","sourceRoot":"","sources":["../../src/theme/cssVars.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAqBjD;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAG,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAI,MAAM,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAkED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,YAAY,CAanE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAM7D"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const ROOT = { selector: ":root", find: /(^|\n)[ \t]*:root[ \t]*\{/g };
|
|
2
|
+
const DARK = { selector: ".dark", find: /(^|\n)[ \t]*\.dark[ \t]*\{/g };
|
|
3
|
+
const THEME = { selector: "@theme inline", find: /(^|\n)[ \t]*@theme(?:[ \t]+inline)?[ \t]*\{/g };
|
|
4
|
+
/** A value that is a colour: a colour function, a `var()` that may hold one, a hex colour or a colour keyword. */
|
|
5
|
+
const COLOUR_VALUE = /^(?:(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color|color-mix|light-dark|var)\(|#[\da-f]{3,8}$|(?:transparent|currentcolor)$)/i;
|
|
6
|
+
/** A token name with its leading `--`, e.g. `--sidebar` for `sidebar`. */
|
|
7
|
+
function property(name) {
|
|
8
|
+
return name.startsWith("--") ? name : `--${name}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @brief Where a block's body ends: the index of its closing brace.
|
|
12
|
+
*
|
|
13
|
+
* @param css - The stylesheet.
|
|
14
|
+
* @param open - Index just past the block's opening brace.
|
|
15
|
+
* @returns The index of the matching closing brace, or `-1` when the braces do not balance.
|
|
16
|
+
*/
|
|
17
|
+
function closingBrace(css, open) {
|
|
18
|
+
let depth = 1;
|
|
19
|
+
for (let i = open; i < css.length; i++) {
|
|
20
|
+
if (css[i] === "{")
|
|
21
|
+
depth++;
|
|
22
|
+
else if (css[i] === "}" && --depth === 0)
|
|
23
|
+
return i;
|
|
24
|
+
}
|
|
25
|
+
return -1;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* @brief Adds the tokens no block of a kind defines, before the closing brace of the first block
|
|
29
|
+
* written as `selector` (so `@theme inline` before a plain `@theme`), else of the first block of the
|
|
30
|
+
* kind, else as a new block at the end. A token any block of the kind defines keeps its value.
|
|
31
|
+
*
|
|
32
|
+
* @param css - The stylesheet.
|
|
33
|
+
* @param block - The kind of block to add to.
|
|
34
|
+
* @param tokens - Tokens by name, with or without the leading `--`.
|
|
35
|
+
* @returns The stylesheet and the names of the tokens added.
|
|
36
|
+
*/
|
|
37
|
+
function addToBlock(css, block, tokens) {
|
|
38
|
+
const bodies = [...css.matchAll(block.find)].flatMap((match) => {
|
|
39
|
+
const open = match.index + match[0].length;
|
|
40
|
+
const end = closingBrace(css, open);
|
|
41
|
+
return end === -1 ? [] : [{ opening: match[0], open, end }];
|
|
42
|
+
});
|
|
43
|
+
const target = bodies.find((body) => body.opening.includes(block.selector)) ?? bodies[0];
|
|
44
|
+
const close = target?.end ?? -1;
|
|
45
|
+
const defined = new Set(bodies.flatMap(({ open, end }) => [...css.slice(open, end).matchAll(/(--[\w-]+)\s*:/g)].map((m) => m[1])));
|
|
46
|
+
const missing = Object.entries(tokens).map(([name, value]) => [property(name), value]).filter(([name]) => !defined.has(name));
|
|
47
|
+
if (missing.length === 0)
|
|
48
|
+
return { css, added: [] };
|
|
49
|
+
const lines = missing.map(([name, value]) => ` ${name}: ${value};\n`).join("");
|
|
50
|
+
const added = missing.map(([name, value]) => ({ block: block.selector, name, value }));
|
|
51
|
+
if (close === -1)
|
|
52
|
+
return { css: `${css.trimEnd()}\n\n${block.selector} {\n${lines}}\n`, added };
|
|
53
|
+
const before = css.slice(0, close);
|
|
54
|
+
return { css: `${before}${before.endsWith("\n") ? "" : "\n"}${lines}${css.slice(close)}`, added };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @brief The names of the `light` and `dark` tokens whose value is a colour, without the leading `--`.
|
|
58
|
+
* A token counts when its light or its dark value is one.
|
|
59
|
+
*
|
|
60
|
+
* @param vars - Tokens to look through.
|
|
61
|
+
* @returns Names such as `sidebar`, each once; `radius: 0.5rem` and `font-sans: Inter` are left out.
|
|
62
|
+
*/
|
|
63
|
+
function colourTokens(vars) {
|
|
64
|
+
const values = [...Object.entries(vars.light ?? {}), ...Object.entries(vars.dark ?? {})];
|
|
65
|
+
const names = values.filter(([, value]) => COLOUR_VALUE.test(value.trim())).map(([name]) => name.replace(/^--/, ""));
|
|
66
|
+
return [...new Set(names)];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @brief Adds the theme tokens a stylesheet lacks: `light` to `:root`, `dark` to `.dark`, `theme` to
|
|
70
|
+
* `@theme inline`. When the stylesheet has a `@theme` block (Tailwind v4), each token whose value is a
|
|
71
|
+
* colour also gets its `--color-<name>: var(--<name>)` mapping there, the way shadcn adds them, so
|
|
72
|
+
* Tailwind classes such as `bg-sidebar` work. Tokens the stylesheet defines, in any block of the same
|
|
73
|
+
* kind, keep their value: the app's theme wins.
|
|
74
|
+
*
|
|
75
|
+
* @param css - The stylesheet, e.g. the contents of `src/index.css`.
|
|
76
|
+
* @param vars - Tokens to add.
|
|
77
|
+
* @returns The stylesheet with the missing tokens added, and which were added.
|
|
78
|
+
*/
|
|
79
|
+
export function addCssVars(css, vars) {
|
|
80
|
+
const hasTheme = [...css.matchAll(THEME.find)].length > 0;
|
|
81
|
+
const mappings = hasTheme ? Object.fromEntries(colourTokens(vars).map((name) => [`color-${name}`, `var(--${name})`])) : {};
|
|
82
|
+
let result = css;
|
|
83
|
+
const added = [];
|
|
84
|
+
for (const [block, tokens] of [[ROOT, vars.light], [DARK, vars.dark], [THEME, { ...mappings, ...vars.theme }]]) {
|
|
85
|
+
if (tokens === undefined || Object.keys(tokens).length === 0)
|
|
86
|
+
continue;
|
|
87
|
+
const merged = addToBlock(result, block, tokens);
|
|
88
|
+
result = merged.css;
|
|
89
|
+
added.push(...merged.added);
|
|
90
|
+
}
|
|
91
|
+
return { css: result, added };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* @brief Merges the theme tokens of several components; the first component naming a token wins.
|
|
95
|
+
*
|
|
96
|
+
* @param all - Tokens per component, in install order.
|
|
97
|
+
* @returns One set of tokens.
|
|
98
|
+
*/
|
|
99
|
+
export function mergeCssVars(all) {
|
|
100
|
+
const merged = { theme: {}, light: {}, dark: {} };
|
|
101
|
+
for (const vars of all) {
|
|
102
|
+
for (const block of ["theme", "light", "dark"])
|
|
103
|
+
merged[block] = { ...vars[block], ...merged[block] };
|
|
104
|
+
}
|
|
105
|
+
return merged;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=cssVars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssVars.js","sourceRoot":"","sources":["../../src/theme/cssVars.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief Finds the project's global stylesheet: the one shadcn's `components.json` names, else the
|
|
3
|
+
* first common location that exists.
|
|
4
|
+
*
|
|
5
|
+
* @param projectRoot - Absolute project root.
|
|
6
|
+
* @returns The path relative to the project root, e.g. `src/index.css`, or `undefined` when none is found.
|
|
7
|
+
*/
|
|
8
|
+
export declare function detectCssFile(projectRoot: string): string | undefined;
|
|
9
|
+
//# sourceMappingURL=detectCssFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detectCssFile.d.ts","sourceRoot":"","sources":["../../src/theme/detectCssFile.ts"],"names":[],"mappings":"AA8BA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIrE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// packages/ui/src/theme/detectCssFile.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/** Where Vite, Next.js and shadcn templates keep the global stylesheet, most common first. */
|
|
6
|
+
const CANDIDATES = [
|
|
7
|
+
"src/index.css",
|
|
8
|
+
"src/app/globals.css",
|
|
9
|
+
"app/globals.css",
|
|
10
|
+
"src/styles/globals.css",
|
|
11
|
+
"styles/globals.css",
|
|
12
|
+
"src/globals.css",
|
|
13
|
+
];
|
|
14
|
+
const ShadcnConfigSchema = z.object({ tailwind: z.object({ css: z.string().min(1).optional() }).optional() });
|
|
15
|
+
/**
|
|
16
|
+
* @brief The stylesheet shadcn's own `components.json` names, when the project has one.
|
|
17
|
+
*
|
|
18
|
+
* @param projectRoot - Absolute project root.
|
|
19
|
+
* @returns The path relative to the project root, or `undefined` when there is no such file or field.
|
|
20
|
+
*/
|
|
21
|
+
function fromShadcnConfig(projectRoot) {
|
|
22
|
+
const file = path.join(projectRoot, "components.json");
|
|
23
|
+
if (!fs.existsSync(file))
|
|
24
|
+
return undefined;
|
|
25
|
+
const parsed = ShadcnConfigSchema.safeParse(JSON.parse(fs.readFileSync(file, "utf8")));
|
|
26
|
+
return parsed.success ? parsed.data.tailwind?.css : undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @brief Finds the project's global stylesheet: the one shadcn's `components.json` names, else the
|
|
30
|
+
* first common location that exists.
|
|
31
|
+
*
|
|
32
|
+
* @param projectRoot - Absolute project root.
|
|
33
|
+
* @returns The path relative to the project root, e.g. `src/index.css`, or `undefined` when none is found.
|
|
34
|
+
*/
|
|
35
|
+
export function detectCssFile(projectRoot) {
|
|
36
|
+
const named = fromShadcnConfig(projectRoot);
|
|
37
|
+
if (named !== undefined && fs.existsSync(path.join(projectRoot, named)))
|
|
38
|
+
return named;
|
|
39
|
+
return CANDIDATES.find((candidate) => fs.existsSync(path.join(projectRoot, candidate)));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=detectCssFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detectCssFile.js","sourceRoot":"","sources":["../../src/theme/detectCssFile.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8FAA8F;AAC9F,MAAM,UAAU,GAAG;IACjB,eAAe;IACf,qBAAqB;IACrB,iBAAiB;IACjB,wBAAwB;IACxB,oBAAoB;IACpB,iBAAiB;CAClB,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAE9G;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,WAAmB;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACvF,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,MAAM,KAAK,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACtF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1F,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@g3nomaly/ui",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.5",
|
|
4
|
+
"description": "Installs React components from any registered source into a project, the way shadcn does.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"
|
|
7
|
+
"g3n-ui": "./dist/cli/index.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "./dist/index.js",
|
|
10
10
|
"module": "./dist/index.js",
|
|
@@ -33,21 +33,20 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
-
"dist"
|
|
36
|
+
"dist",
|
|
37
|
+
"template"
|
|
37
38
|
],
|
|
38
39
|
"scripts": {
|
|
39
40
|
"build:types": "tsc --project tsconfig.build.json",
|
|
40
|
-
"build
|
|
41
|
-
"build:registry": "bun scripts/build-registry.ts",
|
|
42
|
-
"build": "rm -rf dist && bun run build:types && bun run build:components && bun run build:registry",
|
|
41
|
+
"build": "rm -rf dist && bun run build:types",
|
|
43
42
|
"dev": "tsc --project tsconfig.build.json --watch",
|
|
44
43
|
"typecheck": "tsc --noEmit",
|
|
45
44
|
"lint": "eslint src --ext .ts,.tsx",
|
|
46
|
-
"
|
|
45
|
+
"ui": "bun run src/cli/index.ts"
|
|
47
46
|
},
|
|
48
47
|
"dependencies": {
|
|
49
48
|
"@clack/prompts": "^1.7.0",
|
|
50
|
-
"@g3nomaly/core": "^0.3.
|
|
49
|
+
"@g3nomaly/core": "^0.3.5",
|
|
51
50
|
"chalk": "^6.0.0",
|
|
52
51
|
"commander": "^15.0.0",
|
|
53
52
|
"glob": "^13.0.6",
|
|
@@ -61,18 +60,6 @@
|
|
|
61
60
|
"@types/node": "^26.2.0",
|
|
62
61
|
"typescript": "^7.0.2"
|
|
63
62
|
},
|
|
64
|
-
"peerDependencies": {
|
|
65
|
-
"react": "latest",
|
|
66
|
-
"react-dom": "latest"
|
|
67
|
-
},
|
|
68
|
-
"peerDependenciesMeta": {
|
|
69
|
-
"react": {
|
|
70
|
-
"optional": true
|
|
71
|
-
},
|
|
72
|
-
"react-dom": {
|
|
73
|
-
"optional": true
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
63
|
"keywords": [
|
|
77
64
|
"components",
|
|
78
65
|
"ui",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Builds the source: copies src/components to dist/components and writes dist/components.json, which
|
|
2
|
+
// lists every component with a hash per file. Run it with `bun run build`. It runs on Bun only, because
|
|
3
|
+
// it imports each `.meta.ts` file directly.
|
|
4
|
+
//
|
|
5
|
+
// The installer compares those hashes with the files in an app, so `update` installs any change you
|
|
6
|
+
// build, even under the same version. Raise the version in package.json for every release anyway:
|
|
7
|
+
// it is stamped on every component, and `update` shows it as `0.1.0 → 0.2.0`.
|
|
8
|
+
//
|
|
9
|
+
// How apps get the source. Apps add it with `bun add`, not `-d`, when a component keeps files in the
|
|
10
|
+
// package, since the app then imports them at runtime:
|
|
11
|
+
// - npm: `bun publish`. Apps run `bun add <name>`, then `bunx @g3nomaly/ui source add npm:<name>`.
|
|
12
|
+
// - git: commit dist/, since the installer reads a git source as it is and never builds it. Apps
|
|
13
|
+
// install it as `bun add github:<owner>/<repo>#<tag>` and register it as an npm source.
|
|
14
|
+
// - a workspace: put this package and the app in one Bun workspace, add it as `"<name>": "workspace:*"`
|
|
15
|
+
// and register it as an npm source. The best way to work on a source next to an app.
|
|
16
|
+
// - a folder: apps run `bun add file:<path>` and register it as an npm source. When a component keeps
|
|
17
|
+
// files in the package, the installer swaps the link for a packed copy (`bun pm pack`, which runs
|
|
18
|
+
// `prepack` and so this build) on every `add` and `update`, because a link to this folder would load
|
|
19
|
+
// this folder's own node_modules, such as a second React. `source add <path>` reads the folder
|
|
20
|
+
// directly, but cannot serve files kept in the package.
|
|
21
|
+
import fs from "node:fs";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { COMPONENTS_DIR, COMPONENTS_JSON, writeComponentsJson } from "@g3nomaly/ui/registry";
|
|
24
|
+
|
|
25
|
+
const root = import.meta.dir;
|
|
26
|
+
const { version } = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8")) as { version: string };
|
|
27
|
+
const builtDir = path.join(root, COMPONENTS_DIR);
|
|
28
|
+
|
|
29
|
+
fs.rmSync(path.join(root, "dist"), { recursive: true, force: true });
|
|
30
|
+
fs.cpSync(path.join(root, "src", "components"), builtDir, { recursive: true });
|
|
31
|
+
const count = await writeComponentsJson(builtDir, path.join(root, COMPONENTS_JSON), version);
|
|
32
|
+
console.log(`wrote ${COMPONENTS_JSON} with ${count} component${count === 1 ? "" : "s"}`);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "my-components",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React components for @g3nomaly/ui.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"exports": {
|
|
10
|
+
"./*": "./dist/components/*.ts"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "bun build.ts",
|
|
14
|
+
"prepack": "bun run build"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"react": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@g3nomaly/ui": "*"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Colours come from the app's theme: the tokens shadcn and tweakcn define in the app's one globals.css,
|
|
3
|
+
* such as --background, --foreground, --primary, --muted and --border. They switch with dark mode,
|
|
4
|
+
* so a component never needs its own dark styles. Avoid fixed colours. A token of your own goes in
|
|
5
|
+
* `cssVars` in the meta file, which adds it to the app's stylesheet.
|
|
6
|
+
*/
|
|
7
|
+
.my-components {
|
|
8
|
+
&.example {
|
|
9
|
+
padding: 1rem;
|
|
10
|
+
border: 1px solid var(--border);
|
|
11
|
+
border-radius: var(--radius);
|
|
12
|
+
background-color: var(--card);
|
|
13
|
+
color: var(--card-foreground);
|
|
14
|
+
|
|
15
|
+
&--muted {
|
|
16
|
+
background-color: var(--muted);
|
|
17
|
+
color: var(--muted-foreground);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The app gets this file as source and owns it from then on. `update` replaces it only while the app
|
|
2
|
+
// has not changed it, so keep components small and let apps edit them.
|
|
3
|
+
import React from "react";
|
|
4
|
+
// A relative import: Example.css is installed next to this file.
|
|
5
|
+
import "./Example.css";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @brief Props of Example: the native div attributes plus its look.
|
|
9
|
+
*
|
|
10
|
+
* @property tone - Look of the box: `default` or `muted`, set as the `example--<tone>` class.
|
|
11
|
+
*/
|
|
12
|
+
export interface ExampleProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
13
|
+
tone?: "default" | "muted";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Example = React.forwardRef<HTMLDivElement, ExampleProps>(
|
|
17
|
+
({ children, className = "", tone = "default", ...props }, ref) => (
|
|
18
|
+
// `my-components` scopes the CSS of this source, so it does not leak into the app. Use one class
|
|
19
|
+
// per source, named after it.
|
|
20
|
+
<div ref={ref} className={`my-components example example--${tone} ${className}`} {...props}>
|
|
21
|
+
{children}
|
|
22
|
+
</div>
|
|
23
|
+
),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
Example.displayName = "Example";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// The meta file of one component. The build reads every `*.meta.ts` under src/components and writes
|
|
2
|
+
// dist/components.json from them, which is what @g3nomaly/ui reads when it lists and installs components.
|
|
3
|
+
//
|
|
4
|
+
// Rename this file and the component together: `<name>.meta.ts` next to `<Name>.tsx`. One meta file
|
|
5
|
+
// describes one component, and every file in this folder belongs to exactly one meta file.
|
|
6
|
+
import type { PackagedComponent } from "@g3nomaly/ui/types";
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
// The component's name. Its key is this name in lowercase, so people install it with
|
|
10
|
+
// `bunx @g3nomaly/ui add example`. Keys must be unique within this source.
|
|
11
|
+
name: "Example",
|
|
12
|
+
|
|
13
|
+
description: "A starting point for your own component. Replace it.",
|
|
14
|
+
|
|
15
|
+
// The group the component is listed under, and the folder it sits in. Keep the two equal:
|
|
16
|
+
// `add example-group` installs every component in the group. Two sources may use the same group
|
|
17
|
+
// name, in which case the installer asks which one to take, so pick names that say what they hold.
|
|
18
|
+
category: "example",
|
|
19
|
+
|
|
20
|
+
// Every file the component installs. A path is relative to src/components, and the app gets the
|
|
21
|
+
// file at the same path below its own components folder: `example/Example.tsx` lands in
|
|
22
|
+
// `src/components/ui/example/Example.tsx`. Files are copied byte for byte, so any import between
|
|
23
|
+
// files must be relative and must match this layout. Path aliases such as `@/` do not resolve in
|
|
24
|
+
// the app.
|
|
25
|
+
//
|
|
26
|
+
// Types: `component`, `style`, `util`, `hook`, `type`. The meta file itself is added by the build.
|
|
27
|
+
//
|
|
28
|
+
// Logic the app should not edit, such as a store that manages the component's data, stays in this
|
|
29
|
+
// package: mark it `install: "package"` and keep it in the component's folder. The installer never
|
|
30
|
+
// copies it. The component imports it by package path, `import { exampleStore } from
|
|
31
|
+
// "my-components/example/exampleStore"`, which the `exports` field in package.json resolves to
|
|
32
|
+
// dist/components/example/exampleStore.ts. The build fails when no export reaches the file.
|
|
33
|
+
// Apps then need this package installed with `bun add`, and update the store with `bun install`.
|
|
34
|
+
// `add --include-unsafe` gives an app a copy anyway, which its components do not import.
|
|
35
|
+
//
|
|
36
|
+
// Such a file runs in the app, so every package it imports must be in `peerDependencies` of
|
|
37
|
+
// package.json, so it loads the app's copy and not a second one, such as a second React. List it in
|
|
38
|
+
// `devDependencies` too to build here. The build fails on an import that is not a peer.
|
|
39
|
+
//
|
|
40
|
+
// A component needs at least one file the app gets copied; the build fails otherwise. A helper that
|
|
41
|
+
// several stores share needs no meta file of its own: keep it in a component's folder, inside the
|
|
42
|
+
// `exports`, and import it by package path.
|
|
43
|
+
files: [
|
|
44
|
+
{ path: "example/Example.tsx", type: "component" },
|
|
45
|
+
{ path: "example/Example.css", type: "style" },
|
|
46
|
+
// { path: "example/exampleStore.ts", type: "util", install: "package" },
|
|
47
|
+
],
|
|
48
|
+
|
|
49
|
+
// Other components this one needs, installed alongside it:
|
|
50
|
+
// - `card`, a component of this source,
|
|
51
|
+
// - `button@g3n-ui`, a component of another source,
|
|
52
|
+
// - `@shadcn/tooltip`, a shadcn component. shadcn files land in `<components folder>/shadcn/`,
|
|
53
|
+
// so import them as `../shadcn/tooltip` from a group folder.
|
|
54
|
+
registryDependencies: [],
|
|
55
|
+
|
|
56
|
+
// npm packages the files import, as `name` or `name@range`, e.g. `radix-ui` or `recharts@^3`.
|
|
57
|
+
// After `add` and `update`, the installer lists the ones the app's package.json lacks, and adds
|
|
58
|
+
// them with `--install`. Use `devDependencies` for packages needed at build time only.
|
|
59
|
+
dependencies: [],
|
|
60
|
+
|
|
61
|
+
// Theme tokens the CSS uses that a shadcn / tweakcn globals.css does not define, in shadcn's format:
|
|
62
|
+
// names without `--`. After `add` and `update`, the installer adds the ones the app's stylesheet
|
|
63
|
+
// lacks: `light` to `:root`, `dark` to `.dark`, `theme` to `@theme inline`, plus a `--color-<name>`
|
|
64
|
+
// mapping per colour so Tailwind classes such as `bg-example-accent` work. The app's own values win.
|
|
65
|
+
// cssVars: {
|
|
66
|
+
// light: { "example-accent": "oklch(0.7 0.15 250)" },
|
|
67
|
+
// dark: { "example-accent": "oklch(0.5 0.15 250)" },
|
|
68
|
+
// },
|
|
69
|
+
} satisfies PackagedComponent;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
.g3nui {
|
|
2
|
-
&.card {
|
|
3
|
-
border-radius: 0.5rem;
|
|
4
|
-
background-color: white;
|
|
5
|
-
overflow: hidden;
|
|
6
|
-
transition: all 0.2s ease;
|
|
7
|
-
|
|
8
|
-
/* Variants */
|
|
9
|
-
&--default {
|
|
10
|
-
border: 1px solid #e5e7eb;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
&--outlined {
|
|
14
|
-
border: 2px solid #d1d5db;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&--elevated {
|
|
18
|
-
border: 1px solid #e5e7eb;
|
|
19
|
-
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
20
|
-
|
|
21
|
-
&:hover {
|
|
22
|
-
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/* Dark mode support */
|
|
27
|
-
@media (prefers-color-scheme: dark) {
|
|
28
|
-
background-color: #1f2937;
|
|
29
|
-
border-color: #374151;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|